Vue 基础之 mixin 混入、自定义指令、teleport、render 函数、插件和数据校验插件

一、Vue 基础之 mixin 混入、自定义指令、teleport、render 函数、插件和数据校验插件
  1. mixin 混入,组件 datamethods 优先级高于 mixin data 优先级、methods 优先级,组件中有则执行组件中的,组件中没有的则执行 mixin 中的。生命周期函数,先执行 mixin 里面的,再执行组件里面的,如下所示:
const myMixin = {
  data() {
    return {
      number: 2,
      count: 2
    }
  },
  created() {
    console.log('mixin created')
  },
  methods: {
    handleClick() {
      console.log('mixin handleClick')
    }
  }
}

const app = Vue.createApp({
  data() {
    return { number: 1 }
  },
  created() {
    console.log('created');
  },
  mixins: ['myMixin'],
  methods: {
    handleClick() {
      console.log('handleClick');
    },
  },
  template: `
    <div>
      <div>{{number}}</div>
      <div>{{count}}</div>
      <button @click="handleClick">增加</button>
    </div>
  `
});
const vm = app.mount('#root');
  1. mixin 中,自定义的属性,组件中的属性优先级高于 mixin 属性的优先级。如果修改 mixin 优先级高于组件的优先级,可以使用策略配置 optionMergeStrategies 进行修改,如下所示:
const myMixin = {
  number: 1
}

// 全局的 mixin
// app.mixin({
//  data() {
//    return { number: 3 }
//  }
// })

const app = Vue.createApp({
  mixins: [myMixin],
  number: 2,
  template: `
    <div>
      <div>{{this.$options.number}}</div>
    </div>
  `
});

app.config.optionMergeStrategies.number = (mixinVal, appValue) => {
  return mixinVal || appValue;
}

const vm = app.mount('#root');
  1. 自定义指令 directive,如下所示:
// 局部自定义指令
const directives = {
  focus: {
    mounted(el) {
      el.focus();
    }
  }
}

const app = Vue.createApp({
  // directives: directives,
  data() {
    return { hello: true }
  }
  template: `
    <div>
      <div v-if="hello">
        <input v-focus />
      </div>
    </div>
  `
});

// 全局自定义指令
app.directive('focus', {
  beforeMount(el) {
    console.log('beforeMount')
  },
  mounted(el) {
    console.log('mounted');
    el.focus();
  },
  beforeUpdate() {
    console.log('beforeUpdate');
  },
  updated() {
    console.log('updated');
  },
  beforeUnmount() {
    console.log('beforeUnmount');
  },
  unmounted() {
    console.log('unmounted');
  }
});

const vm = app.mount('#root');
  1. 自定义指令后面可以接上一些参数,通过 binding.arg 获取参数,通过 binding.value 获取值,如下所示:
const app = Vue.createApp({
  data() {
    return {
      distance: 110
    }
  },
  template: `
    <div>
      <div v-pos:right="distance" class="header">
        <input />
      </div>
    </div>
  `
});

app.directive('pos', (el, binding) => {
  el.style[binding.arg] = (binding.value + 'px');
});

// app.directive('pos', {
//  mounted(el, binding) {
//    el.style.top = (binding.value + 'px');
//  },
//    el.style.top = (binding.value + 'px');
//  }
//});
const vm = app.mount('#root');
  1. teleport 传送门,如下所示:
const app = Vue.createApp({
  data() {
    return {
      show: false,
      message: 'hello'
    }
  },
  methods: {
    handleBtnClick() {
      this.show = !this.show;
    }
  },
  template: `
    <div class="area">
      <button @click="handleBtnClick">按钮</button>
      <teleport to="#hello">
        <div class="mask" v-show="show">{{message}}</div>
      </teleport>
    </div>
  `
});
const vm = app.mount('#root');
  1. Vuetemplate 变成 render 函数,render 函数再返回一个虚拟 DOM,意义是让 Vue 的性能更快,让 Vue 具备跨平台的能力。render functiontemplate -> render -> h -> 虚拟 DOM,JS 对象 -> 真实 DOM -> 展示到页面上,如下所示:
const app = Vue.createApp({
  template: `
    <my-title :level="2">
      hello Tom
    </my-title>
  `
});

app.component('my-title', {
  props: ['level'],
  render() {
    const { h } = Vue;
    return h('h', this.level, {}, [
      this.$slots.default(),
      h('h4', {}, 'Tom')
    ])
  }
});
const vm = app.mount('#root');
  1. plugin 插件,也就是把通用性的功能封装起来,如下所示:
const myPlugin = {
  install(app, options) {
    app.provide('name', 'Tom');
    app.directive('focus', {
      mounted(el) {
        el.focus();
      }
    });
    app.mixin({
      mounted() {
        console.log('mixin');
      }
    });
    app.config.globalProperties.$sayHello = 'hello world';
  }
}

const app = Vue.createApp({
  template: `
    <my-title />
  `
});

app.component('my-title', {
  inject: ['name'],
  mounted() {
    console.log(this.$sayHello);
  },
  template: `<div>{{name}}<input v-focus /></div>`
});

app.use(myPlugin, { name: 'Tom'});
const vm = app.mount('#root');
  1. 对数据做校验的插件,如下所示:
const app = Vue.createApp({
  data() {
    return { name: 'Jack', age: 22}
  },
  rules: {
    age: {
      validate: age => age > 25,
      message: 'too young, to simple'
    },
    name: {
      validate: name => name.length >= 4,
      message: 'name too short'
    }
  },
  template: `
    <div>name: {{name}}, age: {{age}}</div>
  `
});

const validatorPlugin = (app, options) => {
  app.mixin({
    created() {
      for(let key in this.$options.rules) {
        const item = this.$options.rules[key];
        this.$watch(key, (value) => {
          const result = item.validate(value);
          if (!result) console.log(item.message);
        })
      }
    }
  })
}

app.use(validatorPlugin);
const vm = app.mount('#root');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值