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中组件通讯的数据流向?

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































猜你喜欢

转载自www.cnblogs.com/wuqilang/p/12359571.html