• vue笔记(八)自定义指令 和 mixins混入


    文档:https://cn.vuejs.org/v2/guide/custom-directive.html

    注册指令:

    注册与component注册完全一样:

    • 全局注册:Vue.directive(name,function | object) //object是配置对象,function将会被 `bind` 和 `update` 调用 
    • 局部注册:new Vue({directives:{ name: 配置对象 }})

    模板中使用

      <input v-指令名: xx.a='yy'>这种比较齐全,可以不带.a,也可以不带yy,直接<input v-指令名>。带上的目的是对指令中的动作进行详细的控制

    自定义指令的钩子函数:

      bind,执行一次,指令第一次绑定到元素时调用

      inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)

      update:所在组件的 VNode 变更触发,包括其中的数据变化

     钩子函数的参数:
    • el:指令所绑定的元素,可以用来直接操作 DOM。
    • binding:一个对象,包含以下 property:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
      • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
      • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
      • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
      • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }

    组件钩子函数和指令钩子函数的执行顺序:created, bind, mouted, updata;

    可见,在bind函数执行的时候,操作的是虚拟dom,在updata操作时候,执行的是真实的dom

    例子:注册弹出加载动画的的指令

    <template>
    <div class="home-container" v-vLoading='loadingFlag' /> </template> export default { data() { return { loadingFlag: true, }; }, async created() { this.caroucels = await this.$http.get('/mock/banner'); this.loadingFlag = false; } }
    import Vue from 'vue';
    import loading from '@/assets/loading.svg';//动画文件
    import style from './loading.module.less';//style文件
    
    
    Vue.directive('vLoading', {
      bind (el) {//在第一次指令绑定时候,创建img,并加到绑指令定元素el中
        const img = new Image;
        img.src = loading;
        img.className = style.myLoading;
        img.setAttribute('data-img', 'myLoading');
        el.appendChild(img)
      },
      update(el, binding) {//在数据变化时候,如果img有,则需要删除
        const img = el.querySelector('img[data-img=myLoading]')
        if (!binding.value && img) el.removeChild(img);
      }
    })

    另一个自定义指令的例子:懒加载

    import $bus from '@/utils/eventBus';
    import defaultImg from '@/assets/default-img.jpg';
    import debunce from '@/utils/debunce'

    import Vue from 'vue';
      import vLazy from './lazy'

    let imgArr = []; /** * 检测是否在屏幕上, * @param {*} dom img标签的对象 * @returns */ function inScreen(dom) { const clientHeight = document.body.clientHeight; const info = dom.getBoundingClientRect(); if (info.top + dom.offsetHeight >= 0 && info.top < clientHeight) { return true; } else { return false; } } //加载真实路径 function loadRealImage(img, src) { var temp = new Image(); temp.onload = function () { img.src = src; } temp.src = src; } /** * 防抖函数处理后的回调 */ const debunceDealer = debunce( function () { console.log(imgArr); imgArr = imgArr.filter((element) => { if (inScreen(element.el)) { loadRealImage(element.el, element.src); return false } else { return true } }) },200) $bus.$on('blogMainlScroll',debunceDealer )//当滚动条滚动时候,触发事件,执行debunceDealer export default { inserted(el, binding) { el.src = defaultImg; if (inScreen(el)) { loadRealImage(el, binding.value) } else { imgArr.push({ el, src: binding.value }) } }, unbind(el) { imgArr = [] } }
     

    Vue.directive('vLazy',vLazy)
     <ul class="bloglist">
          <li v-for="item in data.rows" :key="item.id">
            <div class="img" v-if="item.thumb">
              <router-link
                :to="{
                  name: 'blogDetail',
                  params: {
                    blogId: item.id,
                  },
                }"
              >
                <img v-vLazy="item.thumb" :alt="item.title" :title="item.title" />
              </router-link>
            </div>
    
            <div class="content">
              <p class="title">
                <router-link
                  :to="{
                    name: 'blogDetail',
                    params: {
                      blogId: item.id,
                    },
                  }"
                >
                  {{ item.title }}
                </router-link>
              </p>

     混入mixins(vue2中的无奈选择)

    mixins

    • 类型:Array<Object>

    • 详细:

      mixins 选项接收一个混入对象的数组。

      Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。

    var mixin = {
      created: function () { console.log(1) }
    }
    var vm = new Vue({
      created: function () { console.log(2) },
      mixins: [mixin]
    })
    // => 1
    // => 2
    //先执行混入钩子函数,在执行自身钩子函数

    混入应用实例:

      各个组件中,在axios请求时候都会出现请求的动画,请求数据返回时,动画消失。可以提取这一共同特征,作为混入;

    注意:必须标准化几个变量以后用起来方便:

    loadingFlag:加载动画开始结束的锁
    getData:真正的请求数据函数
    mixinsGetData:mixin中的调用getData函数,
     
    //mixin.js
    //将请求的返回值data和请求数据的函数getData来 module.exports = function (data = []) { return { data() { return { data, //默认的请求返回的数据 loadingFlag: true //动画出现的锁 } }, methods: { async mixinsGetData() {
    //以下两句和定义data以及
    this.data = await this.getData(); //将getData函数标准化,每个组件的请求远程数据都是这个函数名 this.loadingFlag = false; } } } }
    <template>
      <div class="home-container" v-vLoading='loadingFlag' >//自定义的loading动画,靠loadingFlag锁开关
      </div>
    </template>
    import mixin from './minxin.js'
    export default{
      mixins:[mixin()]
      methods:{
          async getData(){
              return await this.$http.get('/mock/banner');
          }
      },
        async created() {
            this.mixinsGetData();//调用mixin的函数
      },  
    }
  • 相关阅读:
    Spring 缓存抽象
    Nginx配置入门
    CSS 小结笔记之解决flex布局边框对不齐
    CSS 小结笔记之图标字体(IconFont)
    CSS 小结笔记之em
    CSS 小结笔记之BFC
    CSS 实例之滚动的图片栏
    CSS 实例之翻转图片
    CSS 实例之打开大门
    CSS 小结笔记之伸缩布局 (flex)
  • 原文地址:https://www.cnblogs.com/dangdanghepingping/p/14732557.html
Copyright © 2020-2023  润新知