自定义指令及Vue实例的生命周期

如v-model,v-bind,v-for,v-show等指令都是Vue内置的指令,但可以通过自定义指令来达到其他的效果。
Vue中所有的指令,在调用的时候,都以 v- 开头,所以自定义指令后调用时前面也要加 v- 。

使用 Vue.directive() 定义全局的指令

  1. 第一个参数为指令的名称(注:在定义时,指令的名称前面,不需要加 v- 前缀),但在调用时,必须在指令名称前加上 v- 前缀来进行调用。
  2. 第二个参数是一个对象,这个对象有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作。常用的三个钩子函数为 bind , inserted , update。
  3. bind:每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次。
  4. inserted:表示元素插入到DOM中的时候,会执行inserted函数,触发一次。
  5. update:当组件(或VNode)更新的时候,会执行 update,可能会触发多次。

钩子函数

  1. 第一个参数都为el,表示被绑定了指令的那个元素,这个el参数是一个原生的js对象,可直接用来操作DOM。
  2. 第二个参数binding,是一个对象,常用的属性有(具体可参考Vue.js官网)
    - name:指令名,不包括 v- 前缀
    - value:指令绑定的值(计算结果),如v-my-directive=“1 + 1”,绑定值为2
    - expression:字符串形式的指令表达式,如v-my-directive=“1 + 1”,表达式为"1 + 1"
  • 函数简写: 大多数情况下,可能只在 bind 和 update 钩子上做重复动作,并且不关心其他钩子函数,可以这样写:
Vue.directive('color-swatch',function(el,binding){
	el.style.backgroundColor = binding.value;
	//这个function相当于在bind和update里面都写了一份
})

指令—自定义全局指令让文本框获取焦点,并改变字体样式:

<div id="app">
        <input type="text" v-focus v-fontweight="900">
        <!--不能省略单引号,否则会把blue当作一个变量,而不是字符串-->
        <p v-fontsize="'50px'" v-color="'blue'">{{mes}}</p>
    </div>
    <script>
        Vue.directive('focus', {
            bind: function(el) {
                //在元素刚绑定指令的时候,还没有插入到DOM中去,这时调用focus方法没用
                //因为一个元素只有插入DOM之后才能获取焦点
                //el.focus();
                //样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联样式
                el.style.color = 'red'
            },
            inserted: function(el) {
                el.focus();
            },
            update: function(el) {

            }
        })

        Vue.directive('color', {
            bind: function(el, binding) { //此为形参,可以改变变量名,下面同步即可
                //el.style.color = 'red';
                console.log(binding.name); //color
                console.log(binding.value); //blue
                console.log(binding.expression); //'blue'
                el.style.color = binding.value; //通过binding来拿到传递的值
            }
        })

        //执行任何有关Vue操作前,都要先创建vue实例选定Vue控制区域,否则相关Vue操作都会无效
        var vm = new Vue({
            el: '#app',
            data: {
                mes: '加油!'
            },
            methods: {},
            filters: {}, //定义私有过滤器
            directives: { //自定义私有指令
                'fontweight': {
                    bind: function(el, binding) {
                        el.style.fontWeight = binding.value;
                        //fontWeight第二个单词首字母要大写,不然会失效
                    }
                },
                'fontsize': function(el, binding) {
                    //注意:这个function等同于写在了bind和update中去
                    el.style.fontSize = parseInt(binding.value) + 'px';
                }
            }
        })
    </script>

注: bind在Vue实例创建期间执行created函数时执行,但此时并未将数据渲染到内存中的DOM树,对不在DOM树中的元素调用方法是无效的,在插入DOM树之后调用方法才有效。
所以和JS行为有关的操作,最好在inserted中去执行,防止JS行为不生效。和样式相关的操作,一般都可以在 bind 执行,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联样式,浏览器的渲染引擎会解析样式,应用给这个元素。

Vue实例的生命周期

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

  1. 概念: 从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
  2. 生命周期钩子: 就是生命周期函数(生命周期事件)的别名。
  3. 主要的生命周期函数分类:
    - 创建期间的生命周期函数:beforeCreate、created、beforeMount、mounted
    - 运行期间的生命周期函数:beforeUpdate、updated
    - 销毁期间的生命周期函数:beforeDestroy、destroyed

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue实例的生命周期函数</title>
    <script src="../lib/vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="button" value="修改mes值" @click="mes='快完成啦'">
        <h3 id="h3">{{mes}}</h3>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                mes: '明天继续坚持'
            },
            methods: {
                show() {
                    console.log('执行了show方法')
                }
            },

            //创建期间的生命周期函数
            beforeCreate() { //这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
                console.log(this.mes); //undefined
                //this.show(); //报错:this.show is not a function
            },
            created() { //这是我们遇到的第二个生命周期函数
                console.log(this.mes); //明天继续坚持
                this.show(); //执行了show方法
            },
            beforeMount() { //这是我们遇到的第三个生命周期函数,表示模板以及在内存中编译完成了,但尚未把模板渲染到页面中去
                console.log(document.getElementById('h3').innerText); //{{mes}}
            },
            mounted() { //这是我们遇到的第四个生命周期函数,表示内存中的模板已挂载到页面中去,可以看见渲染好的页面
                console.log(document.getElementById('h3').innerText); //明天继续坚持
            },

            //运行期间的生命周期函数
            beforeUpdate() { //此时数据更新(model)了,但界面(view)还没更新
                console.log('界面上元素的内容:' + document.getElementById('h3').innerText); //界面上元素的内容:明天继续坚持
                console.log('data中的mes数据:' + this.mes); //data中的mes数据:快完成啦
            },
            updated() { //此时已同步更新完成
                console.log('界面上元素的内容:' + document.getElementById('h3').innerText); //界面上元素的内容:快完成啦
                console.log('data中的mes数据:' + this.mes); //data中的mes数据:快完成啦
            }
            //给router-view加了个keep-alive导致组件缓存了,所以不会触发beforeDestory和destoryed
        })
    </script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/qq_46469137/article/details/107557695