一,vue核心属性
1,计算属性
在vue实例的data中,里面的key值就是属性名,里面的value就是属性值,而这个计算属性,就是用来对data中的数据进行一个属性计算的,将里面的数据进行一个加工操作,生成一个全新的数据。计算属性的数据通过这个computed保存。
new Vue({ data:{firstName:'郑',lastName'三'}, computed:{ fullName:{ //当有人读取这个fullName时,get就会被调用,且返回值就作为fullName的值 get(){ return this.firstName + '-' + this.lastName; } } } })
并且在这个fullName中的get()函数,会做一个缓存。并且只有在第一次读取这个fullName时,或者所需要的data中的数据发生变化时,这个get方法才会发生调用,之后再有的别人来读取这个fullName的值的时候,就直接读取缓存中的值了。
只有在这个computed中会有缓存,在methods中是没有缓存中。computed的底层主要是通过数据代理,通过其底层的getter和setter来实现的。
以上部分也可以直接对 fullName 这一部分做一个简写,直接写成如下部分,并且只有在只做获取,不做修改时才能简写成以下部分。但是需要切记的是这个fullName的值可以由这个vue实例直接获取到,而不是获取一个函数。
fullName(){ return this.firstName + '-' + this.lastName; }
2,监视属性
使用watch关键字,对data中的数据进行监听,除了可以监听data中的数据,也可以监听计算属性中的值。在数据发生改变时,handler这个监听方法就会被触发。
new Vue({ data:{isHot:true}, watch:{ //监视data中的isHot属性 isHot:{ immediate:true,//初始化这个handler时调用一下 handler(newVlaue,oldVlaue){ console.log('isHot被修改了',newVlaue,oldVlaue) } } } })
如果需要监视多级结构中的属性变化,那么需要加入一个属性deep,这样主要该结构中的任意一个数据发生变化,就会触发这个handler函数。
deep:true
如果不需要这个deep和这个immediate属性,那么可以将这个isHot属性进行一个简写操作,如下
isHot(newVlue,oldValue){ console.log('isHot被修改了',newVlaue,oldVlaue) }
在既可以用监视属性,又可以用计算属性完成某个功能时,当面临这个异步事件的时候,优先使用监视属性;除此之外,可以优先使用计算属性。
3,样式绑定
3.1,class样式绑定
对于确定的样式,可以直接使用这个class来直接绑定,对于这个不确定的样式使用 :class 双向绑定来确定
<!-- 绑定class样式,字符串写法 --> <div class="basic" :class="mood">{{name}}</div> <!-- 绑定class样式,数组写法 --> <div class="basic" :class="dataArr">{{name}}</div> <!-- 绑定class样式,对象写法 --> <div class="basic" :class="dataObj">{{name}}</div>
3.2,style样式绑定
除了可以使用绑定这个class,也可以手动的写这个style
<!-- 绑定对象的写法 --> <div class="basic" :style="styleObj1">{{name}}</div> <!-- 绑定数组的写法 --> <div class="basic" :style="styleArr">{{name}}</div>
其实例中的data属性如下
styleObj1:{ fontSize: '40px', color: 'red, backgroudColor: 'orange' } styleObj2...
4,条件渲染
顾名思义就是说,满足什么条件,就渲染对应的东西。 如下可以使用这个v-show这个指令来实现,其底层主要是操作这个dispaly这个指令,当为true时该结点展示,当为false时该结点隐藏。
v-show="true"
除了这个v-show,也可以使用这个v-if来实现条件渲染。但是如果直接使用v-if,其底层会直接将该结点删除,而不是隐藏,如果要显示的话,那么就得重新添加一个结点。
v-if = "true"
因此在选择中,如果切换的频率高的话建议使用v-show,如果切换的很低的话可以选择v-if。如果在切换的频率很高的情况使用这个v-if,那么就会进行大量的增加和删除结点,在一定程度上会影响一定的效率。
而在选择这个v-if的时候,除了使用这个v-if,也会使用这个v-else-if,v-else,可以三个结合一起使用。
v-if = "n===1" v-else-if = "n===2" v-else
并且在这几个结合体中,不允许出现中断操作,即这几个指令要结合并且连在一起使用。
5,列表渲染
5.1,遍历列表
主要使用这个v-for来表示,其内部就类似于一个for循环,然后遍历一个数组。并且为了保证数组中每一条数据的唯一性,最好加一个key标识,并且这个key使用每一条元素中的id。除了数组,对象,字符串等都是可以直接进行遍历的。
<div id="root"> <h2>人员列表</h2> <ul> <li v-for = "(p,index) in persons" :key = p.id> {{p.name}} - {{p.age}} </li> </ul> </div> //在vue实例的data中的数据如下 data:{ persons:[ {"id":001,name:'张三',age:18,}, {"id":002,name:'李四',age:19,}, {"id":003,name:'王五',age:20,} ] }
5.2,key的作用
在这个虚拟dom中,有一个diff的高效的比较算法,而在该算法中,需要利用上这个key。因此在对这个key进行一个值的赋予时,优先选择一个唯一的id,如后台给的id或者index下标,如果不涉及到列表的更新的话,那么这两个都可以使用,如果涉及到这个列表更新的话,那么只考虑使用这个唯一id。
使用index作为key,就会出现如下情况。input输入框的数据发生错乱,并且需要重新生成多个虚拟dom,效率相对而言较底下,并且渲染之后的界面直接出现问题
使用唯一id,只要重新生成一个新增数据对应的虚拟dom即可,而原先的虚拟dom以及对应的数据可以直接进行一个复用操作。
5.3,key的作用
key是虚拟DOM的标识,当数据发生变化的时候,Vue会根据新数据生成新的虚拟DOM,随后新旧虚拟DOM会进行一个比较操作
新旧虚拟DOM的比较规则如下:
1,若旧虚拟DOM找到了与新虚拟DOM中相同的key
若虚拟DOM中内容没变,直接使用之前的真实DOM
若虚拟DOM中的内容变了,则重新生成新的真实DOM
2,旧虚拟DOM未找到与新虚拟DOM相同的key
直接创建新的真实DOM,随后渲染到页面上
所以在开发中,建议直接选择唯一标识,如后台返回的id,手机号,身份证号等唯一值。
5.4,列表过滤
可以直接使用关键字filter对列表中的数据进行一个过滤,如上面的这个person数组,将年级大于18的所有数据给过滤出来。
this.persons.filter((p)=>{ return p.age > 18; })
5.5,列表排序
在数据过滤时,往往也需要对数据进行一个排序操作。接下来模拟一个根据年龄进行排序的实现,如下:
this.persons.sort((p1,p2) =>{ //sortType:: 1,升序 2,降序 return sortType === 1 ? p1.age - p2.age : p2.age-p1.age; })
6,Vue.set() 的使用
可以通过这个vue.set将后来加入的值变成响应式,使其后边加入的值变成有setter和getter两个构造函数。
//向student这个对象中加入sex这个性别以及对应的值 //如果实在methods中,则可以直接使用this即可 Vue.set(vm.student,'sex','男')
也可以使用vm.$set ,其效果和这个Vue.set() 一样
vm.$set(vm.student,'sex','女')
并且在添加属性时,这个第一个参数不能为Vue的实例对象或者根数据对象,只能是vm对象里面的属性。
7, Vue监测数组中数据改变的原理
vue在使用数组时,只有在以下方法中才能触发视图更新的操作。并且一下七个方法是经过了Vue包裹的几个方法
push() pop() shift() unshift() splice() sort() reverse()
当然除了上面的七个方法,也可以使用6中的这个set方法,对里面的值进行设置或者添加。
// 对hobby数组中的第一个数据改成打篮球 Vue.set(vm.student.hobby,0,'打篮球')
7.1,监测数据操作总结如下。
<body> <!-- 一个容器,可以用于接收vue实力传来的数据,然后展示 --> <div id="root" aglian> <h2>学生信息</h2> <button @click="student.age++" >年龄+1岁</button> </br></br> <button @click="addSex()" >添加性别属性,默认值男</button> </br></br> <button @click="addFriend" >在列表首位添加一个朋友</button> </br></br> <button @click="updateFirstFriendName" >修改第一个朋友的名字为张三</button> </br></br> <button @click="addHobby" >添加一个爱好</button> </br></br> <button @click="UpdateFirstHobby" >修改第一个爱好为:开车</button> </br></br> <h1>姓名:{{student.name}}</h1> <h2>年龄:{{student.age}}</h2> <!-- v-if也可以 --> <h2 v-show="student.sex">性别:{{student.sex}}</h2> <h2>学生爱好</h2> <ul> <li v-for = "(p,index) in student.hobby" :key = p.id> {{p}} </li> </ul> <h2>朋友们</h2> <ul> <li v-for = "(p,index) in student.friends" :key = p.id> {{p.name}} - {{p.age}} </li> </ul> </div> <script type="text/javascript" > Vue.config.productionTip = false //阻止vue启动时提示生产提示 new Vue({ //指定当前实例为哪个容器服务,id对应#,class对应. el:'#root', //data用于存储数据,只有el对应的容器可以使用 data:{ student:{ name:'tom', age:18, hobby:['打篮球','看书','跑步'], friends:[ {name:'zhs',age:19}, {name:'lisi',age:20}, ] } }, methods:{ addSex(){ Vue.set(this.student,'sex','男'); }, addFriend(){ // 只要用了那七个包装的方法,修改的值就可以变成响应式 this.student.friends.unshift( {name:'Jack',age:21}); }, updateFirstFriendName(){ // 没有set和get的属性都不是响应式,修改值时vue不认 // 数组没有setter和getter,但是数组中的属性是有setter和getter的 this.student.friends[0].name = '张三'; }, addHobby(){ this.student.hobby.push('画画'); }, UpdateFirstHobby(){ //Vue.set(this.student.hobby,0,'开车') this.$set(this.student.hobby,0,'打羽毛球') } } }) </script> </body>
7.2,数据监测原理总结如下
1,Vue会监视data中所有层次的数据
2,监测对象中的数据如下
通过setter实现监视,且要在new Vue时就要传入要监测的数据
(1)对象中后追加的属性,Vue默认不做响应式处理
(2)如需给后添加的属性做响应式,可以使用如下两种方式
Vue.set(target,propertyName/index,value)或 vm.$set(target,propertyName/index,value)
3,监测数组中的数据
通过包裹数组更新元素的方法实现,本质就是做了两件事
(1).调用原生对应的方法对数组进行更新
(2).重新解析模板,进而更新页面
4,Vue修改数组中的某个元素
(1)使用上面七个封装后的方法
(2)使用Vue.set()或者 vm.$set()
特别注意:Vue.set()或者 vm.$set()不能给vm或者vm的根数据对象添加属性
(2)如需给后添加的属性做响应式,可以使用如下两种方式
Vue.set(target,propertyName/index,value)或 vm.$set(target,propertyName/index,value)
3,监测数组中的数据
通过包裹数组更新元素的方法实现,本质就是做了两件事
(1).调用原生对应的方法对数组进行更新
(2).重新解析模板,进而更新页面
4,Vue修改数组中的某个元素
(1)使用上面七个封装后的方法
(2)使用Vue.set()或者 vm.$set()
特别注意:Vue.set()或者 vm.$set()不能给vm或者vm的根数据对象添加属性