zoukankan      html  css  js  c++  java
  • vue-day05----自定义指令(directive)、render和template的区别、mixin混入、Vue.use()、Vue.extend()、Vue.filter()、vue中的数据流向

    ### 自定义指令  directive

        全局自定义指令:Vue.directive()
        局部自定义指令:directives
        directive(参数一,参数二)
            参数一:指令名称
            参数二:指令的配置项,可以是函数,也可以是对象
                函数:
                    参数一:使用当前指令的元素
                    参数二:指令的详细信息
                        {
                            modifiers:修饰符(只要自定义指令后面跟了修饰符,modifiers对象中就有值,为true),
                            value:指令的值(假设指令这样写:<div v-test="'aaa'"></div>,那么value就是aaa)
                        }
                        
        
        指令的作用:操作DOM元素
        步骤:
            ①src下新建utils/utils.js:
    import Vue from "vue";
    
    /**
     *  v-test指令:
     *      <div v-test="'发发发'"></div>
     *      相当于
     *      <div>发发发</div>
     * 
     */
    Vue.directive("test",(el,{value})=>{
        el.innerText=value;
    });
    
    /**
     *  设置背景颜色的指令 
     * 
     */
    Vue.directive("backgroundColor",(el,{value,...rest})=>{
        el.style.backgroundColor=value;
    });
    
    /**
     *  阻止浏览器默认事件:v-event.prev
     * 
     */
    Vue.directive("event",(el,{modifiers})=>{
        let {prev}=modifiers;
        el.addEventListener("contextmenu",(e)=>{
            if(prev){
                e.preventDefault();
            }
        });
    });
    
    /**
     *  自动聚焦
     * 
     */
    Vue.directive("focus",{
        // 获取光标在inserted中操作,此时元素已经插入到父节点了
        inserted(el){
            el.focus();
        }
    });
    
    /**
     *  第一个参数是指令名称,第二个参数如果是一个函数,这个函数是指令要做的事情,如果是一个对象,这个对象是指令的配置项。
     * 
     * 
     */
    Vue.directive("wql",{
        bind(){ 
            // 当前元素使用当前指令的时候会被调用,只会调用一次,用来做初始化
            console.log("bind")
        },
        inserted(){
            // 当使用指令的元素被插入到父节点(#app)的时候会被触发
            console.log("inserted")
        },
        update(){
            // 只要当前元素不被移除,其他操作几乎都会触发这2个生命周期,先触发update后触发componentUpdate
            // 虚拟DOM只要涉及到元素的隐藏、显示(display)值的改变、内容的改变等都会触发虚拟DOM更新
            console.log("update")
        },
        componentUpdated(){
            console.log("componentUpdate")
        },
        unbind(){
            // 当只用指令的元素被卸载的时候会执行,简单的说就是当前元素被移除的时候
            console.log("unbind")
        }
    });
    
    
    /**
     *  v-drag
     * 
     */
    Vue.directive("drag",(el,{modifiers,value})=>{
        if(value){
            var disX,disY;
            var {l,t} = modifiers;
            el.style.position = "absolute";
            el.addEventListener("mousedown",mousedown)
            function mousedown(e){
                disX = e.offsetX;
                disY = e.offsetY;
                document.addEventListener("mousemove",move)
                document.addEventListener("mouseup",up)
            }
            function move(e){
                var x = e.clientX - disX;
                var y = e.clientY - disY;
                if((l&&t) || (!l&&!t)){
                     el.style.left = x + 'px';
                     el.style.top = y + 'px';
                     return;
                }
                if(l){
                    el.style.left = x + 'px';
                     return;
                }
                if(t){
                    el.style.top = y + 'px';
                     return;
                }
            }
            function up(){
                document.removeEventListener("mousemove",move)
                document.removeEventListener("mouseup",up)
            }
        }
    });
            ②main.js中引入:
                import "./utils/utils.js";
            ③App.vue中使用自定义指令:
                <div v-test="'发发发'" v-backgroundColor.not="'blue'"></div>
                <div v-test="'阻止浏览器默认事件'" v-backgroundColor="'yellow'" v-event.prev></div>
                <input type="text" v-focus>
        指令的生命周期:
            bind():当元素只用当前指令的时候会被调用,只会调用一次,用来做初始化
     
            inserted():当使用指令的元素被插入到父节点(#app)的时候会被触发
     
            update():只要当前元素不被移除,其他操作几乎都会触发这2个生命周期,先触发update后触发componentUpdate。虚拟DOM什么时候更新:只要涉及到元素的隐藏、显示(display)值的改变、内容的改变等都会触发虚拟DOM更新
     
            componentUpdate():组件更新
     
            unbind():当使用指令的元素被卸载的时候会执行,就是当前元素被移除的时候

    ### render和template的区别

        template----html的方式做渲染
        render----js的方式做渲染
     
        render(提供)是一种编译方式
        render里有一个函数h,这个h的作用是将单文件组件进行虚拟DOM的创建,然后再通过render进行解析。
        h就是createElement()方法:createElement(标签名称,属性配置,children)
     
        template也是一种编译方式,但是template最终还是要通过render的方式再次进行编译。
     
        区别:
            1、render渲染方式可以让我们将js发挥到极致,因为render的方式其实是通过createElement()进行虚拟DOM的创建。逻辑性比较强,适合复杂的组件封装。
            2、template是类似于html一样的模板来进行组件的封装。
            3、render的性能比template的性能好很多
            4、render函数优先级大于template

    ### mixin   混入

        通过mixins引入组件后,会给当前组件额外扩展一些属性和方法,简单的说就是给组件额外添加了一个BUFF
     
        封装插件的时候用mixin
     
        mixin----全局使用
        mixins----局部使用
     
        步骤:
            ①utils下新建mixin.js:
                export default {
                    // new Vue()中的配置项都可以在这里加
                    data(){
                        return{
                            title:"我是额外提供的一个属性"
                        }
                    },
                    created() {
                        console.log("我是一个buff")
                    }
                }
            ②App.vue中引入:
                import Mixin from "./utils/mixin.js";
            ③添加mixins属性:
                mixins:[Mixin],
            此时在created中就多一个console.log打印,在App.vue页面可以直接使用title属性,就和写在自己的data中一样。

    ### Vue.use()

        Vue.use()是用来使用插件的,当前插件如果导出的是一个函数,那么这个函数就会被当做install方法。如果当前插件导出的是一个对象,那么这个对象必须提供一个install方法,因为Vue.use()在使用这个插件的时候会给install方法提供一个Vue构造函数。
     
        注:所有的插件都创建了一个install方法,再将install方法导出。
     
        使用场景:如果在编写插件的时候通过外部的方式来引入Vue的时候会使这个插件变得特别大,此时需要用到Vue.use(),它的作用就是给插件传递一个vue。
     
        步骤:
            ①src下新建plugins/wql.js:
                // 如果导出一个函数,这个函数会被当做是install方法,同时Vue.use()会给这个函数传递Vue的构造函数,不用引入直接就有
                // export default (Vue)=>{
                //     console.log(Vue)
                // }
    
                // 如果导出一个对象,这个对象必须要提供install方法,同时Vue.use()会给这个方法传递Vue的构造函数
                export default {
                    install(Vue){
                        console.log(Vue)
                    }
                }
            ②main.js中引入并使用wql.js:
                import wql from "./plugins/wql.js";
                Vue.use(wql); // 打印vue的构造函数

    ### Vue.extend()

        作用:让编写好的组件可以当成方法使用,就是将ui组件转换为js组件。
        步骤:
            ①src下新建publics/index.vue和publics/index.js文件:
                在index.vue中写好组件,在index.js中引入再通过Vue.extend()继承,转换成js组件
                import messageBox from "./index.vue";
                import Vue from 'vue';
                // options对象是Message()中的参数对象
                export default (options)=>{
                    // 继承Vue,将js对象来继承Vue,来转换成js组件,这个js组件可以被放在页面的任何地方
                    let MessageBox=Vue.extend(messageBox);
                    let vmMessage=new MessageBox({
                        el:document.createElement("div"),
                        // 这里是继承的Vue,所以有和vue一样的配置项,可以写data、methods、生命周期...
                    }
                    // $mount()返回一个对象,其中有$el,$el就是赋给el的div
                    document.body.appendChild(vmMessage.$mount().$el);
                }
            ②main.js中引入并使用:
                import Message from "./plugins/message/index.js";
                Vue.use(Message);
                此时页面上就已经显示了组件,因为install方法是自动执行的。
     
            ③不在main.js中引入,直接在需要使用的组件(App.vue)中引入:
                import Message from "./plugins/message/index.js";
                然后在created()中执行 Message(); 就会在页面上显示出来,Message()中可以写一个{},将属性和方法传递给options。
     

    ### Vue.filter()

        作用:过滤数据
     
        语法:
            全局:
                Vue.filter("过滤器名",(参数一,参数二)=>{});
                    参数一:需要过滤的数据
                    参数二:传递的数据
     
            局部:
                filters:{
                    过滤器名(){
     
                    }
                }
        
        使用:{{username|过滤器名()}}
     
        步骤:
        (1)时间过滤器
            ①声明一个全局过滤器
                Vue.filter("date",(data,icon)=>{
                    let year=(new Date(data)).getFullYear();
                    let month=(new Date(data)).getMonth()+1;
                    let day=(new Date(data)).getDate();
                    var icon=icon||"/";
                    return `${year}${icon}${month}${icon}${day}`; 
                });
            ②实例中设置一个time:
                let vm=new Vue({
                    el:"#app",
                    data:{
                        time:(new Date()).getTime()
                    }
                });
            ③管道符进行使用:
                {{time|date("-")}}
        (2)图片尺寸过滤器
            ①data中将imgUrl引入:
                data(){
                    return{
                        imgUrl:"http://p0.meituan.net/w.h/movie/2c24eb6a84a92b9ba837967851bec9462844109.jpg"
                    }
                }
            ②声明局部filters:
                filters:{
                    imgReplace(data,wh){
                        // 将字符串 "w.h" 替换为 "170.280"
                        return data.replace(/w.h/,wh);
                    }
                }
            ③页面中使用:
                <img :src="imgUrl|imgReplace('170.280')">

     

    ### Question:

    vue中组件通讯的数据流向?

        在组件通讯的时候数据的流向是单向数据流。
     
        在组件通信的时候父组件传递给子组件的状态,子组件只允许做访问,不能做修改。如果需要做修改则需要在自己内部保存一份再进行修改。因为如果子组件改变了父组件的状态,会导致数据流难以理解。































  • 相关阅读:
    srvany.exe和instsrv.exe_2
    srvany.exe和instsrv.exe
    C# “国密加密算法”SM系列的C#实现方法
    DMZ讲解
    java 判断字符串是否为json格式
    MFC DrawText如何使多行文字居中显示 Demo
    C++ 实现一个日志类
    数据库两个神器【索引和锁】
    CentOS 7.*编译安装PHP8
    Centos添加永久环境变量
  • 原文地址:https://www.cnblogs.com/wuqilang/p/12359571.html
Copyright © 2011-2022 走看看