美文网首页
vue查缺补漏

vue查缺补漏

作者: 饥人谷_米弥轮 | 来源:发表于2019-11-19 01:26 被阅读0次
    1. Object.defineProperty有缺陷,就是无法监控到对象属性临时添加的属性,必须使用VUE.set($set)属性去添加,这个方法原理就是重新设定一个Object.defineProperty监听新属性,所以VUE3.0改为使用proxy去监听,没有这种缺陷

    2. 数组在添加过程中也是会无法监听的,所以在VUE中写了push,pop,shift ...这类直接修改数组方法(因为不修改原数组的方法是会返回新数组的,可以通过监听新数组去触发)的变异方法,通过改写这类方法进行数组值的监听,例:

    let push = Array.prototype.push
    Array.prototype.push = function(...args) {
        // 中间做些类似中间件的代码,获取新增的数据,进行监听
        ....
        push.call(this, ...args)
    }
    

    3.v-once只渲染一次
    4.v-pre忽略这个元素和它子元素内容的编译
    5.v-model修饰符

    v-model.lazy,取代change方法,等输入完之后再进行输出
    v-model.number,只能输入数字
    v-model.trim,收尾空格去除
    

    6.鼠标修饰符

    .stop,阻止冒泡
    .self,点击事件绑定元素与当前元素一致时才会触发
        //stop和self分别什么情况下使用,当子元素不想产生冒泡触发父级事件时使用stop,
        //而self则时在很多嵌套元素情况下,只想触发当前元素的时候使用
    .prevent,阻止默认事件
    .once,事件只绑定一次
    .passive,告诉浏览器没有阻止默认事件
        //每次触发事件,浏览器都要等线程执行到事件监听器对应的代码时,才能查询代码是否有阻止默认事件这个行为,而这个查询过程会导致在使用scroll,手势,移动等事件出现卡顿,
        //添加上这个修饰符后就是直接告诉浏览器没有做这个行为,就不用去查询了
        //原生写法:el.addEventer('click', function() {}, {once:true,passive:true})
    

    7.键盘修饰符

    .exact,精确键盘事件
       //@keyDown.ctrl.exact="fn" 表示只能在单独按ctrl键的时候才能触发
    

    8.watch

    new Vue({
      el: '#app',
      data: {
        a: {
          b: {
            c: 1
          }
        }
      },
      watch: {
        'a.b.c': {
          handler: function(new, old) { console.log() },   //对于多层数据的监听,可以使用字符串+点语法
          immediate: true, //当第一次绑定值时就直接监听
          deep: true //深层监听,最多监听5层
        }
        
      }
      //
    })
    

    9.v-model在除input元素外的使用

    <div id="app">
      <child v-model="val"></child>  
    </div>
    
    const child= {
        model: {
                // 指定v-model绑定的prop属性,需要和下方props的属性名对应
                prop: 'checked',
                // 执行内部触发的哪个事件会修改指定的prop
                event: 'check'
        },
        props: ['checked'],
        data() {
                return {
                        status: this.checked
                }
        },
        template: `
                <div class="kkb-radio" :class="{'checked': status}" @click="changeStatus"></div>
        `,
        methods: {
                changeStatus() {
                        this.status = !this.status;
                        this.$emit('check', this.status);
                }
        }
    };
    
    let vm = new Vue({
        el: '#app',
        data: {
                val: true
        },
        components: {
                'kkb-radio': kkbRadio,
                'kkb-plane': kkbPlane
        },
        methods: {
                change(status) {
                        this.val = status;
                }
        }
    });
    

    10.作用域插槽

    <div id="app">
        <dialog :datas="datas">
            <template v-slot:title="data">
                <h1>{{data.title}}</h1>
            </template>
    
            <template v-slot:default="data">
                <ul>
                    <li v-for="user of data.users">
                        {{user.username}}
                    </li>
                </ul>
            </template>
        </dialog>
    </div>
    
    <script>
        const Dialog = {
            props: ['datas'],
            template: `
                    <div class="dialog">
                            <i class="dialog_close_btn"></i>
                            <div class="dialog_header">
                                    <slot :title="datas.type" name="title"></slot>
                            </div>
                            <div class="dialog_content">
                                    <slot :users="datas.users"></slot>
                            </div>
                    </div>
                `
        };
    
        new Vue({
            el: '#app',
            data() {
                return {
                    datas: {
                        type: '学员',
                        users: [{
                                id: 1,
                                username: 'baogege',
                                gender: '男',
                                checked: false
                            },
                            {
                                id: 2,
                                username: 'mt',
                                gender: '男',
                                checked: false
                            },
                            {
                                id: 3,
                                username: 'haigege',
                                gender: '男',
                                checked: false
                            },
                            {
                                id: 4,
                                username: 'zMouse',
                                gender: '男',
                                checked: false
                            },
                            {
                                id: 5,
                                username: 'reci',
                                gender: '女',
                                checked: false
                            },
                            {
                                id: 6,
                                username: 'lisi',
                                gender: '女',
                                checked: false
                            }
                        ]
                    }
                }
            },
            components: {
                'dialog': Dialog
            }
        });
    </script>
    
    

    11.生命周期

    //捕获子孙组件错误
    new Vue({
      .....
      errorCaptured(err, vm, info) {
          //err:  错误信息
          //vm:  错误的组件对象
          //info:  错误类型
       }
    })
    

    12.动态加载组件,keep-alive组件

    <div id="app">
        <button @click="goto('InBox')" :class="{'current': currentComponent==='InBox'}">收邮件</button>
        <button @click="goto('PostMail')" :class="{'current': currentComponent==='PostMail'}">发邮件</button>
        <button @click="goto('RecycleBin')" :class="{'current': currentComponent==='RecycleBin'}">垃圾箱</button>
        <hr>
        <keep-alive>
                <component :is="currentComponent"></component>
        </keep-alive>
    </div>
    
    <script>
        const InBox = {
            data() {
                return {
                    items: [
                        '111111',
                        '22222222222',
                        'aaaaaaaa',
                        '3333333'
                    ]
                }
            },
            template: `
                <div>
                    <ul>
                        <li v-for="item of items">
                            <input type="checkbox" />
                            {{item}}
                        </li>
                    </ul>
                </div>
            `,
            created() {
                console.log('InBox:created');
            },
            destroyed() {
                console.log('InBox:destroyed');
            },
            activated() {  //添加keep-live后新增的生命周期,启用的时候触发
                console.log('InBox:activated');
            },
            deactivated() {  //添加keep-live后新增的生命周期,冻结的时候触发
                console.log('InBox:deactivated');
            }
        }
        const PostMail = {
            template: `
                <div>PostMail</div>
            `,
            created() {
                console.log('PostMail:created');
            },
            destroyed() {
                console.log('PostMail:destroyed');
            },
            activated() {  //添加keep-live后新增的生命周期,启用的时候触发
                console.log('PostMail:activated');
            },
            deactivated() {  //添加keep-live后新增的生命周期,冻结的时候触发
                console.log('PostMail:deactivated');
            }
        }
        const RecycleBin = {
            template: `
                <div>RecycleBin</div>
            `,
            created() {
                console.log('RecycleBin:created');
            },
            destroyed() {
                console.log('RecycleBin:destroyed');
            },
            activated() {  //添加keep-live后新增的生命周期,启用的时候触发
                console.log('RecycleBin:activated');
            },
            deactivated() {  //添加keep-live后新增的生命周期,冻结的时候触发
                console.log('RecycleBin:deactivated');
            }
        }
        
        let app = new Vue({
            el: '#app',
            data: {
                currentComponent: 'InBox'
            },
            components: {
                InBox,
                PostMail,
                RecycleBin
            },
            methods: {
                goto(target) {
                    this.currentComponent = target;
                }
            }
        });
    </script>
    

    13.自定义组件

    new Vue({
      el: '#app',
      directives: {
        '指令名称' : {指令配置}
      }
    })
    
    ###  指令生命周期
    - bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
    - inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
    - update : 所在组件更新的时候调用
    - componentUpdated : 所在组件更新完成后调用
    - unbind : 只调用一次,指令与元素解绑时调用
    
    ###  例子
    <script>
    Vue.directive('drag', {
        bind(el, {modifiers,value}) {
            let isDragStart = false;
            let disX = 0;
            let disY = 0;
            el.canDrag = value;
            el.addEventListener('mousedown', e => {
                if (!el.canDrag) return;
                disX = e.clientX - el.offsetLeft;
                disY = e.clientY - el.offsetTop;
                isDragStart = true;
    
                e.preventDefault();
            });
            document.addEventListener('mousemove', e => {
                if (isDragStart) {
                    let x = e.clientX - disX;
                    let y = e.clientY - disY;
    
                    if (modifiers.limit) {
                        if (x < 0) {
                            x = 0;
                        }
                        if (y < 0) {
                            y = 0;
                        }
                    }
    
                    el.style.left = x + 'px';
                    el.style.top = y + 'px';
                }
            });
            document.addEventListener('mouseup', e => {
                isDragStart = false;
            });
        },
        componentUpdated(el, {value}) {
            console.log('componentUpdated', value);
            el.canDrag = value;
        }
    });
    
    let app = new Vue({
        el: '#app',
        data: {
            canDrag: false
        }
    });
    </script>
    

    14.路由守卫

    ###  组件内路由
    beforeRouteEnter(to, from, next) {  //路由组件进入前
      //这个阶段不能访问this,组件未创建
      //实在需要访问的话
      next(vm => { console.log(vm) })
    }
    beforeRouteUpdate(to, form, next) {}  //当前路由变化,但该组件属于复用时调用
    beforeRouteLeave(to, form, next) {}  //离开对应路由时调用
    
    ###  路由独享守卫
    beforeEnter(to, from, next) {} //直接使用在路由中, 如:
      const router = new VueRouter({
        routes: [
          {
            path: '/foo',
            conponent: Foo,
            beforeEnter: (to, from, next) => {}
          }
         ]
      })
    
    ### 全局路由守卫
    router.beforeEach((to, from, next) => {})
    router.beforeResolve((to, from, next) => {})
    router.beforeEach((to, from) => {})  //导航被确认后调用,就是在整个路由完成最后调用的生命周期
    

    15.route组件的props

    //路由中可以定义props属性,值为`true/false`。
    //router.js
    const router = new VueRouter({
      ...
      routers: [
        {
          path: '/home/:itemId',
          name: 'home',
          compoment: Home,
          props: true
        }
      ]
    })
    `使用了props属性后,那么在组件中就不需要使用this.$route.params.itemId进行获取,可以直接在组件的props:['itemId']中获取到`
    
    // child.vue
    export default {
      ...
      props:['itemId'],
      created() { console.log(this.itemId) }
    }
    
    `PS: vue在处理props传值时,如果在组件中的props没有定义所传的属性名,将会保存在this.$attrs中,如:
    //parent.vue
    <div id="app">
      <child a="1" b="2" c="3"></child>
    </div>
    
    //child.vue
    export default {
      props: ['a'],
      data() {
        return {}
      },
      created() { console.log(this.$attrs) }    //{b:2, c:3}
    }
    `
    
    `路由props有三种处理模式`
    //1.默认处理
    //直接将route.params中的数据和组件中props的数据进行合并
    
    //2.对象模式
    //有选择的返回props
    {
      path: '/home/:itemId',
      compoment: home,
      props: {a:1, b:2}
    }
    
    //3.回调函数模式
    {
      path: '/home/:itemId',
      compoment: home,
      props: r => ({itemId: Number(r.params.itemId)})
    }
    

    16.切换路由时,页面滚动条保持/归顶

    //必须使用浏览器前进回退功能(使用js触发前进回退也行)
    const router = new VueRouter({
      scrollBehavior(to, from, savedPosition) {
        if(savedPosition) {
          return savedPosition  //保存上一页的x、y坐标
        } else {
          return {x: 0, y: 0}
        }
      },
      routes: [...]
    })
    

    相关文章

      网友评论

          本文标题:vue查缺补漏

          本文链接:https://www.haomeiwen.com/subject/tnhsictx.html