【vue系列-03】vue的计算属性,列表,监视属性及原理

简介: 【vue系列-03】vue的计算属性,列表,监视属性及原理

一,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,效率相对而言较底下,并且渲染之后的界面直接出现问题

3444145a79994098ab8cac2286ad4cac.png

使用唯一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的根数据对象添加属性

相关文章
|
4天前
|
前端开发 JavaScript
Vue底层实现原理总结
Vue底层实现原理总结
8 0
|
8天前
|
JavaScript 前端开发 测试技术
使用 Vue CLI 脚手架生成 Vue 项目
通过 Vue CLI 创建 Vue 项目可以极大地提高开发效率。它不仅提供了一整套标准化的项目结构,还集成了常用的开发工具和配置,使得开发者可以专注于业务逻辑的实现,而不需要花费大量时间在项目配置上。
67 7
使用 Vue CLI 脚手架生成 Vue 项目
|
6天前
|
JavaScript
|
7天前
|
存储 JavaScript API
Vue状态管理深度剖析:Vuex vs Pinia —— 从原理到实践的全面对比
Vue状态管理深度剖析:Vuex vs Pinia —— 从原理到实践的全面对比
13 2
|
10天前
|
JavaScript 算法
“Error: error:0308010C:digital envelope routines::unsupported”启动vue项目遇到一个错误【已解决
“Error: error:0308010C:digital envelope routines::unsupported”启动vue项目遇到一个错误【已解决
11 1
|
10天前
|
JavaScript
error Component name “Login“ should always be multi-word vue/multi-word-component-names【已解决】
error Component name “Login“ should always be multi-word vue/multi-word-component-names【已解决】
25 1
|
3天前
|
JavaScript 前端开发
Vue躬行记(7)——渲染函数和JSX
Vue躬行记(7)——渲染函数和JSX
8 0
|
6天前
|
缓存 监控 JavaScript
Vue.js中的计算属性 computed 与监听属性 watch深入探索
Vue.js中的计算属性 computed 与监听属性 watch深入探索
27 0
|
11天前
|
JavaScript API
【vue实战项目】通用管理系统:信息列表,信息录入
【vue实战项目】通用管理系统:信息列表,信息录入
19 3
|
11天前
|
JavaScript API
【vue实战项目】通用管理系统:信息列表,信息的编辑和删除
【vue实战项目】通用管理系统:信息列表,信息的编辑和删除
26 2