Vue05-自定义指令+生命周期

 


Vue05-自定义指令+生命周期

1.自定义指令-自定义v-big和v-find指令

<body>
<div id="app">
    <!--
        1 定义v-big指令,功能和v-text指令类似,但是会将绑定的数字放大10倍。
    -->
    <p>n值 <span v-text="n"></span></p>
    <p>放大10倍的n值 <span v-big="n"></span></p>
    <button @click="n++">n++</button>

    <!--
        1 v-big没有绑定name值,但是name被修改了,big函数也被调用。
        2 name被修改,模板被重新解析,big函数也会被调用。
    -->
    <p>{{name}}</p>
    <button @click="name = 'alice'">修改name</button>

    <!-- 2 定义v-fbind指令,功能和v-bind类型,但是会使元素获取焦点。 -->
    <input type="text" v-fbind01="n">
    <input type="text" v-fbind02="n">
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            n: 1,
            name: 'tom'
        },
        // directives用于自定义指令。
        directives: {
            // 1 自定义的big指令可以是一个函数,函数有两个参数。
            //      1 element,element是绑定v-big指令的真实DOM元素。
            //      2 binding,binding为绑定指令的信息。

            // 2 big函数调用的时机。
            //      1 指令和元素绑定成功时调用。
            //      2 指令所在模板被重新解析时调用。
            big(element, binding) {
                console.log(element); // <span></span>
                console.dir(element);
                console.log(element instanceof HTMLElement); // true

                console.log(binding); // {name: 'big', rawName: 'v-big', value: 1, expression: 'n', modifiers: {…}, …}

                // binding.value获取指令绑定的值。
                element.innerHTML = binding.value * 10;
            },
            fbind01(element, binding) {
                element.value = binding.value;

                // fbind01在指令和元素绑定成功时执行,但是此时元素并没有被加载到DOM中,
                // 所以给元素设置焦点是无效的。
                element.focus();
            },

            // 自定义指令的第二种写法,自定义指令可以是一个对象。
            // 当指令被定义为对象时,对象中可以定义三个方法,这三个方法vue会在指定的时间调用。
            fbind02: {
                // 指令和元素绑定成功时调用。
                bind(element, binding) {
                    element.value = binding.value;
                },
                // 指令所在元素被插入页面时调用。
                inserted(element, binding) {
                    // 此时元素已经被插入页面,所以给元素设置焦点是有效的。
                    element.focus();
                },
                // 指令所在模板被重新解析时调用。
                update(element, binding) {
                    element.value = binding.value;
                }
            }
        }
    });
</script>
</body>

2.自定义指令-获取焦点执行时间的问题

<body>
    <button id="btn01">创建输入框</button>
    <button id="btn02">创建输入框</button>
    <script>

        // 当获取焦点的代码在元素未放入DOM中是无效的。
        document.getElementById('btn01').onclick = function () {
            const input = document.createElement('input');
            // 让创建的输入框获取焦点。
            input.focus();
            // 设置元素value的代码在放入DOM前后都是有效果的。
            input.value = 'tom';

            document.body.appendChild(input);
        };

        // 获取焦点的代码在元素放入DOM之后,获取焦点有效果。
        document.getElementById('btn02').onclick = function () {
            const input = document.createElement('input');
            document.body.appendChild(input);

            input.value = 'alice';
            input.focus();
        };
    </script>
</body>

3.自定义实例-自定义全局指令和自定义指令总结

<body>
<div id="app">
    <!--
        自定义指令总结。
            1 定义语法。
                局部指令。new Vue({directives: {}})
                全局指令。Vue.directive(指令名, 配置对象) 或者 Vue.directive(指令名, 回调函数)。

            2 当指令为对象时,对象中常用的三个回调。
                bind,指令和元素成功绑定时调用。
                inserted,指令所在元素被插入页面时调用。
                update,指令所在模板结构被重新解析时调用。

            3 指令在定义时不需要加v-,但是在使用时需要加v-。
            4 指令名如果是多个单词,则需要使用a-b的形式,而不能使用驼峰命名aB的形式。

    -->

    <!-- 1 当指令的为多个单词时的写法。 -->
    <span v-big-number="n"></span>

    <!-- 2 所有指令中的this都是window,不管指令是函数形式还是对象形式,自定义指令中的this都是window。 -->
    <span v-big="n"></span>
    <input type="text" v-fbind="n">

    <!-- 3 自定义全局指令。 -->
    <p>自定义全局指令</p>
    <span v-big01="n"></span>
    <input type="text" v-fbind01="n">
</div>
<script>
    // 1 定义全局的指令,函数式。
    Vue.directive('big01', function (element, binding) {
        element.innerHTML = binding.value * 20;
    });
    // 定义全局的指令,对象式。
    Vue.directive('fbind01', {
        bind(element, binding) {
            console.log('bind', this); // window
            element.value = binding.value * 30;
        },
        inserted(element, binding) {
            console.log('inserted', this); // window
            element.focus();
        },
        update(element, binding) {
            console.log('update', this); // window
            element.value = binding.value;
        }
    });

    const vm = new Vue({
        el: '#app',
        data: {
            n: 1
        },
        // vue实例中定义的都是局部指令
        directives: {
            // 当自定义指令为多个单词时,需要使用下划线_连接,所以属性的key要使用原始写法。
            'big-number': function (element, binding) {
                let n = binding.value;
                element.innerHTML = n * 100;
            },
            big(element, binding) {
                console.log('big', this); // window
                let n = binding.value;
                element.innerHTML = n * 100;
            },
            fbind: {
                bind(element, binding) {
                    console.log('bind', this); // window
                    element.value = binding.value;
                },
                inserted(element, binding) {
                    console.log('inserted', this); // window
                    element.focus();
                },
                update(element, binding) {
                    console.log('update', this); // window
                    element.value = binding.value;
                }
            }
        }
    })
</script>
</body>

4.生命周期-引出生命周期

<body>
<div id="app">
    <!--
    1 生命周期又称为生命周期回调函数、生命周期函数、生命周期钩子函数。
    2 Vue的生命周期是指Vue在关键时刻调用一些特殊名称的函数。
    3 生命周期函数的名称不可更改,但是生命周期函数的内容可以由程序员定义。
    4 生命周期函数中的this指向vm或者组件实例对象。
    -->
    <span :style="{opacity: opacity}">学习vue</span>
    <span :style="{opacity: n}">学习vue</span>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            opacity: 1,
            n: 1
        },
        // Vue完成模板解析并把初始的真实DOM放入页面后调用mounted。
        mounted() {
            console.log("Vue完成模板解析");
            console.log(this); // mounted中的this是Vue实例vm
            // 2 vue中定义定时器的方式二,初始化时调用,并且只调用一次。
            setInterval(() => {
                this.n -= 0.1;
                if (this.n <= 0) {
                    this.n = 1;
                }
            }, 1000);
        }
    });

    // 1 vue中定义定时器的方式一,在vue实例外部定位,不推荐使用。
    setInterval(() => {
        vm.opacity -= 0.1;
        if (vm.opacity <= 0) {
            vm.opacity = 1;
        }
    }, 1000);
</script>
</body>

5.声明周期-分析生命周期

<body>
<div id="app">
    <span>n的当前值{{n}}</span>
    <br>
    <button @click="add">n+1</button>
    <button @click="destroy">销毁</button>
</div>

<div id="root01">
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            n: 1
        },
        methods: {
            add() {
                console.log('add');
                this.n++;
            },
            destroy() {
                this.$destroy();
            }
        },
        // 初始化流程。
        beforeCreate() {
            console.log('beforeCreate');
            // debugger; // 执行到当前后暂停。
        },
        created() {
            console.log('created');
        },
        // 挂载流程。
        beforeMount() {
            console.log('beforeMount');
        },
        mounted() {
            console.log('mounted');
            // vm.$el此时是真实的DOM,
            console.log(this.$el);
            console.log(this.$el instanceof HTMLElement); // true
        },

        // 更新流程。
        beforeUpdate() {
            console.log('beforeUpdate');
        },
        updated() {
            console.log('updated');
        },
        // 销毁流程。
        // 销毁会撤销watch中对属性的监视。
        beforeDestroy() {
            console.log('beforeDestroy');
            // beforeDestroy()依然可以进行方法的调用,
            // 但是所调用的方法如果会修改页面数据的值,则不会在进行页面数据的更新。
            this.add();

        },
        destroyed() {
            console.log('destroyed');
        }
    });

    const vm01 = new Vue({
        el: '#root01',
        data: {
            n: 1
        },
        // 可以将模板代码定义在template中。
        // template中的代码会替换<div id="root01"></div>和其内部的所有代码。
        // template中的代码要求只有一个根节点。
        // template在组件中使用。
        template: `<div>
            <span>n的当前值{{n}}</span>
            <br>
            <button @click="n++">n+1</button>
        </div>`
    })
</script>
</body>

6.声明周期-总结生命周期

<body>
<div id="app">
    <!--
        1 Vue声明周期函数。
            beforeCreate、created、beforeMount、mounted、
            beforeUpdate、updated、beforeDestroy、destroyed。

        2 常见的声明周期函数。
            1 mounted,可以发送ajax请求、开启定时器、绑定自定义事件、订阅消息。
            2 beforeDestroy,可以消除定时器、解绑自定义事件、取消消息订阅。

        3 关于销毁Vue实例。
            1 销毁后借助Vue开发工具看不到任何信息。
            2 销毁后自定义事件会失效,但是原生DOM定义的事件依然有效(通过@click绑定的事件)。
            3 一般不会在beforeDestroy中操作数据,因为即使操作了数据,也不会触发数据更新的流程。
    -->
    <span :style="{opacity: opacity}">学习vue</span>
    <button @click="stop">stop</button>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            opacity: 1,
        },
        methods: {
            stop() {
                this.$destroy();
            }
        },
        mounted() {
            // 将开启定时器返回的id保存到Vue实例中,方便清除定时器时使用。
            this.timer = setInterval(() => {
                this.opacity -= 0.1;
                if (this.opacity <= 0) {
                    this.opacity = 1;
                }
            }, 100);
        },
        beforeDestroy() {
            console.log('销毁之前');
            clearInterval(this.timer);
        }
    });

</script>
</body>
posted @   行稳致远方  阅读(272)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示