Vue key属性详解 &&自定义插件&&自定义指令

1、key的作用

作为一个DOM节点的标识值,结合Diff算法可以实现节点的复用。(key相同的节点会被复用)
只有当key(或其他导致isSameNode判断为false)发生改变时,才会触发节点的重新渲染。否则Vue将会复用之前的节点,通过改变节点的属性来实现节点的更新。
<button @click="addEmployee">添加员工</button>
<ul>
<!-- 列表渲染时,key值最好是对象的唯一属性值,比如:学号,工号,身份证号,手机号等待
      目的是:当列表更新时,提高后期的渲染性能。
      因为vue在渲染数据时,先将数据生存一份虚拟DOM,再将虚拟DOM生成对应的真实DOM挂载到页面中
      当vue中的数据修改后,会重新生成一份虚拟DOM,并跟之前的虚拟DOM进行匹配,
      如果两份虚拟DOM中的key和key对应的值完全相同,不会重新生成对应的真实DOM
      只有key和key对应的值不同的虚拟DOM,才会生成新的真实DOM并挂载的页面中。-->
     <li v-for="(item) in employees" :key="item.id">{{item}}</li>
</ul>
export default {
  name: 'Home',
  data() {
    return {
      //定义一个工程师数组
      employees:[
        {
          id:1001,
          name:'刘德华',
          age:20,
          sex:'男'
        },
        {
          id:1002,
          name:'张学友',
          age:22,
          sex:'男'
        }
      ]
    }
  },
}
 methods: {
    //添加员工的方法
    addEmployee(){
      let emp = {
        id:Date.now(),
        name:'蔡依林',
        sex:'女',
        age:26
      }
      this.employees.unshift(emp)
    }
  },

2、key使用id与index区别

不推荐使用index作为key,因为这种做法会导致某些节点被错误的原地复用,具体如下:
性能损耗:列表渲染时会导致变动项往后的所有列表节点(内容)的更新(相当于key没有发挥作用)
出现错误:某些节点在错误的位置被复用。(例如列表项中使用到复选框时)

3、 Vue.nextTick()方法

定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

所以就衍生出了这个获取更新后的DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 js代码;
理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,
<div class="one">
    <input type="text" v-model="carName" />
    <button @click="addCar">添加汽车</button>
    <ul ref="list">
      <li v-for="item in cars" :key="item.id">
        <input :value="item.name" />
      </li>
    </ul>
    <hr>
    <button @click="employee.name='蔡依林'">修改姓名</button>
    <button @click="addSex">添加性别</button>
    <div>{{employee}}</div>
  </div>
data() {
    return {
      //汽车名称
      carName: "",
      //汽车数组
      cars: [
        {
          id: 1001,
          name: "玛莎拉蒂",
        },
        {
          id: 1002,
          name: "帕拉梅拉",
        },
      ],
      employee:{
          name:'周杰伦',
          age:20
      }
    };
  },
methods: {
    addCar() {
      let car = {
        id: Date.now(),
        name: this.carName,
      };
      this.cars.push(car);
      this.carName = "";
      // $nextTick方法,需要传一个回调函数,
      // 回调函数里面的代码在DOM更新完成后执行。
      this.$nextTick(() => {
        // 让最后一个li元素里面的input元素获取焦点
        this.$refs.list.lastChild.lastChild.focus();
      });
},
addSex(){
        // this.$set(this.employee,'sex','男')
        // 直接添加的属性,不具备响应式
        this.employee.sex='男'
        // $forceUpdate()方法,迫使 Vue 实例重新渲染
        this.$forceUpdate()
    }
注意:Vue实现响应式并不是数据发生变化之后DOM立即变化,而是按照一定的策略进行DOM的更新。nextTick是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用nextTick,则可以再回调中获取更新后的DOM。

4、自定义指令

<div v-red>好好学习</div>
    <p v-red>天天向上</p>
    <div v-html="car" v-color="'red'"></div>
    <div v-myhtml="car" v-color="'green'"></div>
 data() {
      return {
          car:'<h2>保时捷卡宴真好看</h2>'
      }
  },
//定义局部指令,所有的指令背后都是在操作DOM,我们将这种功能称之为:造轮子。
directives:{
      //自定义一个指令,指令名称是myhtml,
      //自定义指令就是一个方法,该方法有两个参数:返回指令所在的dom元素,绑定的一份数据   
      myhtml:function(el,binding){
          el.innerHTML = binding.value
      },
      red:function(el){
          el.style.color = 'red'
      },
      color:function(el,binding){
          el.style.color = binding.value
      }
}

5、自定义插件

定义一个插件,插件就是将给Vue添加的全局成员,归类到一起去,这样做利于后期维护。
在src新建一个plugins文件夹,在新建一个index.js

// 插件本质上就是一个对象
export default {
    // 该对象中必须包含一个install()方法
    // install()方法的第一个参数是Vue,第二个参数是配置对象
    // install()方式,会在use的时时候执行,
    // Vue.use(插件),这里的Vue会作为install方法的第一个参数
    install:function(Vue,options){
        // 可以直接给Vue添加成员
        Vue.sayHi = function(){
            console.log('大家好!我是Vue');
        },
        Vue.msg = "欢迎是插件",
        // 可以在Vue的原型上扩展成员
        Vue.prototype.sayHello = function(){
            console.log('哈哈!我是Vue原型上的方法');
        },
        // 给Vue混入成员
        Vue.mixin({
            data() {
                return {
                    plane:{
                        name:'奔驰',
                        price:'100W'
                    }
                }
            },
            methods: {
                showPlane(){
                    console.log(this.plane.name,this.plane.price);
                }
            },
        }),
        // 注册全局组件
        Vue.component('b-box', {
            // 在脚手架环境中,只能通过渲染函数定义全局组件
            render(h) {
                return h('div',this.$slots.default)
            },
        }),
        // 注册全局指令
        Vue.directive('bgcolor', function(el,bind){
            el.style.backgroundColor = bind.value
        })
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容