我是{{name}}
3.然后我们再尝试绑定属性,就以name属性为例
在上面的div中添加name属性并绑定到Vue的值:
我是{{name}}
v-bind也可以简写为: 你没看错就是冒号,所以上面的等价于下面
我是{{name}}
这种绑定有个缺点就是当标签中的属性值发生改变时,Vue中的值并不会发生变化,这时候就要用到v-model,v-model专门用于input表单场景中,我们新创建一个表单测试
这样当输入框中文本发生改变时,Vue中的name值也会发生改变!
mvvm模型就是model view viewmodel三个缩写,二Vue扮演的角色就是在model和view中间的viewmodel,它将底层的数据model,经过自己的处理展现到界面上,这就是viewmodel,简称vm。
Object.defineproperty("要更改属性的对象",要变化的属性,{键值对};
var people = {
name: "chenpei",
sex: "女"
}
//向对象中添加属性
Object.defineProperty(people,"age",{
value: 22,
writable: true,
//规定添加的属性值能否被修改。
enumerable: true,
//规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
});
所以通过这种方法赋值和普通的赋值具有本质上的不同,这也是Vue底层选用的原因。
var people = {
name: "chenpei",
sex: "女"
}
var peopleTwo = {
name: "wuji",
sex: "男",
}
//向对象中添加属性
Object.defineProperty(people,"age",{
value: 22,
writable: true,
//规定添加的属性值能否被修改。
enumerable: true,
//规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
});
//修改peopleTwo的getter和setter
Object.defineProperty(peopleTwo,"sex",{
//当有人从peopleTwo中读取sex属性时,会执行get方法获得people中sex属性的值
get(){
return people.sex;
},
//同上理,当有人修改sex属性时,people中的sex属性也会被setter改变
set(value){
people.sex = value;
}
});
2.Vue底层就用到了这种数据代理,请看下图(图片来源:尚硅谷)
3.这样实现数据代理之后,Vue即vm将自身_data对象中储存的数据被vm自身代理,实现数据同步,这样也方便了我们在插值语法中书写,只需要写数据名即可。
我是{{name}}
控制台输出内容:
我是{{name}}
控制台内容如下:
由以上内容我们可以知道:
myClick(event,num){
//取消冒泡
event.stopPropagation();
//在控制台输出测试
console.log(event,num);
//看看事件的触发者
console.log("内部button的触发者是:" + event.target);
}
然后当我们点击按钮的时候就只有最里面的函数得到执行。
也能阻止冒泡
prevent | 阻止元素默认事件,像a标签的跳转等等 |
stop | 阻止冒泡 |
once | 事件仅允许触发一次 |
capture | 使用事件的捕获模式,就是由外到内执行函数 |
self | 只有Event.target是自己的时候才执行函数,如果在例子中加入此,也可阻止冒泡 |
passive | 事件的默认函数立即执行,无需等待回调函数执行完毕 |
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
另一方面,当与现代化的工具链以及各种支持类库结合使用时,
Vue 也完全能够为复杂的单页应用提供驱动。
结果是每当我在内容上面通过鼠标滚轮滚动时,要等一万个我行输出完毕,滚动条才会移动内容才会变化。
2.要取消这种行为,只需要修饰符passive
四、按键别名与键盘事件
(一)什么是按键别名?
当我们绑定键盘事件的时候,事件对象会自动获取你所按的按键的别名和键码保存在属性中
下面例子用input元素的keyup事件来在控制台获取按键别名,利用event.key属性
再给按键事件指定特定的键触发,需要加上if判断语句
if(ev.keyCode == 13)//十三是回车键的键码 console.log("您按的键是:" + ev.key); }
(二)Vue键盘别名绑定事件快捷方式
- 格式:
@keyup.键盘别名 ="要绑定的函数";
- 常见的键盘别名:enter(回车)、delete(删除键和退格键)、esc(退出)、tab(换行)、 up\down\right\left(上下左右)
- 要注意有些键已经绑定了浏览器事件,要注意,比如tab点下去就会转移元素焦点,所以该键只能配合keydown使用。还有alt control shift 和徽标键,属于修饰键,如果用keyup的话只有control键不动按住其他键松开才会生效,要想单独使用就要用keydown了。
@keyup.ctrl.y = "函数" 按住ctrl和y,y起才能执行函数
- 还要注意,有些键盘别名是驼峰命名,要想用.的方式,命名要改为纯小写中间用-隔开 ,举例如下
@keyup.caps-lock ="函数"
修饰符可以连着写
五、Vue属性与计算属性
(一)属性
- Vue中的属性是在data中定义的:
- 那么我们利用属性来实现个效果,两个输入框,一个span,当输入框内容发生改变时,span中内容也要发生改变。
(二)Vue的计算属性
- 像上面span中的内容是有Vue中的两个属性计算出来的就可以指定为一个计算属性,以满足Vue在html界面上的简洁化。
- Vue计算属性的声明:
最终效果和上面一致。
- 再加上set,来实现,当页面加载完成后,更改fullname的值后,Vue中的相关属性也发生改变
set(value){ var zu = value.split("-");//将值以-为间隔拆分成数组 this.firstName = zu[0]; this.lastName = zu[1]; }
实现效果,我更改fullname的值,自动调用setter
属性值也跟着变化:
- 这种方式跟插值的方式比有什么优点呢?
- 页面更加清晰。
- 计算属性有缓存,当fullName被多次调用时,get方法只用执行一次,只有当fullName相关联的属性值发生变化时,才会再次执行;而插值语法动态绑定不一样,只要是Vue中的属性变化,都要重新再读取属性值。
(三)Vue中计算属性的简写
- 使用简写的前提条件是:确定计算属性只需要计算并展示,并不会被修改(即没有setter)的情况下,才可以使用。
- 据此上面的fullName计算属性可以直接改写为:相当于getter了
fullName(){ return this.firstName + "-" + this.lastName; }
六、监视属性
(一)什么是监视属性?
- 它能够监视Vue中的属性值和计算属性值,当他们发生变化时,执行一些自定义的逻辑
- 语法,以监视上面例子的fullName为例:
watch:{ fullName:{ handler(newValue,oldValue){ console.log("属性发生了改变变化前的值是:" + oldValue ); } } }
然后我们修改在页面控制台修改fullName的值,发现watch的handler执行了
(二)监视属性案例练习
我爱着{{rel}}!
效果是当季节发生变化,我爱的天气发生变化,同时season属性被监控,改变前后的值被输出到控制台
- 另一种监视写法:
vm.$watch(要监视的变量,{handler函数和一系列原数据对});
(三)深度属性监视
- 当属性里面有对象(即层级结构时,需要用到深度属性监视),看下面例子。
当number中a的值发生改变的时候,控制台输出它的上一个值,而b值的变化不会影响到handler函数:
a的值是:{{number.a}}
b的值是:{{number.b}}
- 那么如何实现number中只要有值改变就触发函数呢?修改一下代码,仅展示watch部分:
watch:{ number:{ deep: true, //不开启这个参数,Vue的watch就无法看到直接属性内的数据 //因为选的是上层结构,所以这里传入的参数发生了改变,是一个对象,里面分别有a和b的新值 handler(old){ console.log("a或b的值发生了改变,原来的值是:" + "a的新值是" +old.a +"b的新值是:" + old.b); } } }
这样两者的变化都能触发handler函数了
七、Vue中使用函数时的this指代
- 当Vue中是Vue中规定的要写函数的地方,我们用普通的函数声明方法,当中的this指代的是Vue实例vm。仅举例子:
- 当Vue需要用setTimeout这种js原生函数时,用传统的函数声明(或调用)方法,那么里面的this就是windows对象,要是用箭头函数this就指代的是vm对象。
- 原因,当用箭头函数声明时,this指的是拥有者,普通方式是函数的调用者。
- 所以由以上总结出最佳实践,当是vue规定的函数时,用普通声明方式,当用到原生函数时且涉及到Vue中属性的this调用,要用箭头函数声明。
八、class样式绑定和style属性的绑定(上面学习内容的综合练习)
(一)class样式绑定练习
- 首先我们要明确一点:
- 下面这种情况div是可以同时使用上面三种样式的:
- 用数组方式实现div三种样式的随机切换:
测验通过!
- 用数组的方式动态让用户改变样式,用对象的方式
我是神仙不下凡点击第一个按钮效果:
再点击第二个按钮增加居中效果:
(二)style属性样式动态绑定
- 需要用到样式对象,要声明在Vue中
- 例子,放大文本的字体到45px;
- 原来的写法:
2 .Vue动态绑定的写法
我是神仙不下凡
两种方式效果一致:
九、v-if和v-show的简单使用
(一)两者的异同之处
- 相同之处
- 可以单独使用,不用跟标签属性绑定。
- 都只能是布尔值,可以在Vue中读取值。
- 如果为false都能做到让元素消失
- 不同之处
- v-show值为false时,实际上是改变了元素的display属性值为none,但是元素节点还在。
- v-if值为false时,就是直接把元素节点删除了
(二)v-if的整体使用
- 简单的例子,改变v-if的值来控制元素的出现与消失。直接利用上面例子,仅需要注意v-if和a的绑定值即可
我是神仙不下凡我们在控制台模仿用户改变a的值让元素消失:
- v-if可以和v-else-if以及v-else一起使用实现多级判断。
第一个第二个最后一个因为默认a为0,前面几个条件都不满足,所以v-else生效:
然后我们模仿用户修改a的值
- 使用上面的配套if这几个div中间不能被其他没带v-if的元素打断,否则就会报错
- 当使用标准的v-if,v-else-if,那么当有一个条件满足,其他的都直接略过为false。
十、列表渲染(v-for的使用)
(一)使用前置信息
- v-for的形式:
{{value.对应的键名}}
- 这样书写后,在加载界面的时候,v-for就会帮我们遍历在Vue中对应的对象,并且增加对应数量的li
- 在遍历时会从对象或数组中获取两个内容,一个是对应的值,另一个是键或者下标
- :key需要动态绑定一个值,保证每个li的唯一性,这里用的是数组下标。
- 插值语法中的变量也可以来自v-for中的形参。
(二)案例演示
- 遍历一个数组,数组中储存的是对象,那么遍历拿到的就是对象
- {{obj.name}}-{{obj.age}}-love:{{obj.love}}
效果:
(三)案例使用的key绑定为数组下标的隐患
一、Vue的虚拟dom对比算法,那我们修改上面的例子为例,仅展示增加部分
--------------------------- methods:{ addPeople(){ var wang = {name:"老王",age: 22,love: "云韵"}; //将新人推入数组,注意从前面进入 this.peoples.unshift(wang); } }
- 这里我们增加了一个按钮,实现点击增加新人。那么在这个过程中虚拟dom是如何实现对比算法的呢?
- 页面加载时的虚拟dom中有三个对象,分别是路飞、鸣人、萧炎,然后我们点击按钮,数组中的数据发生变化了,就会触发虚拟dom的对比算法,对比算法根据key值确定对比双方
这样还会连累无辜,导致出错,例如每个li中都加了一个输入框
{{obj.name}}-{{obj.age}}-love:{{obj.love}} 加载完页面后,我们在输入框输入各自对应的数据,
然后点击添加新人错误出现:input内容全乱了!
- 解决方法,
- 将数据从后面插入。
- 将key值指定为每个对象中的唯一值,这样key的对应对象就固定了,那么diff算法对比的对象就都一样了。
十一、列表过滤
(一)用监听属性来实现
列表搜索
- {{value.name}}--{{value.age}}--love:{{value.love}}
(二)用计算属性实现
列表搜索
- {{value.name}}--{{value.age}}--love:{{value.love}}
(三)在给表格添加根据年龄排序的功能
列表搜索
- {{value.name}}--{{value.age}}--love:{{value.love}}
十一、Vue如何实现对自身实例中属性的监控?
(一)重温Vue中的数据
- Vue中的数据都在data中,分为数组和对象两种类型。在其中声明的数据会受到Vue实例vm的管理
- 那么如何管理?
- 就对象而言,当vm创建完成之后,Vue中data中的对象以及对象中的每个键都会被增加getter和setter方法,放在vm._data这个属性中,同时数据代理到了vm.一级属性名中.
- 如下
- {{people.name}}--{{people.age}}
- {{people.name}}--{{people.age}}--{{people.love}}
加载完页面如下:
我们模仿用户在vm中添加love属性。
添加完后,love的数据并没有被解析,这说明数据虽然添加了,但是Vue并没有发现属性值的增加,而新添加的属性也绝没有setter和getter。
- {{people[0]}}--{{people[1]}}--{{people[2]}}
应使用语句:
修改值,使用splice函数
vm._data.people.splice(0,1,"鸣人");
增加值,使用push();
可见都修改成功
应使用语句
格式:
Vue.set(要添加属性的对象,要添加或修改的属性,属性值);
或者
vm.$set((要添加属性的对象,要添加或修改的属性,属性值);
具体:
vm.$set(vm._data.people,"love","雏田");
Vue.set(vm._data.people,"love","雏田");
效果:
这样的话收集到的数据都会转化为数值