⑤ vue 中的高级用法

vue 中的高级用法

1 Mixin 混入的基础语法

1.1 组件 data methods 优先级高于 mixin data 优先级

1.2 生命周期函数先执行 mixin 的再执行组件的

const myMixin = {
  data() {
    return { 
      number: 2,
      count: 2
    }
  },
  created() {
    console.log('mixin created');
  },
  methods: {
    handleClick() {
      console.log('maxin 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.3 局部 mixin

const myMixin = {
  data() {
    return { 
      number: 2,
      count: 2
    }
  },
  created() {
    console.log('mixin created');
  },
  methods: {
    handleClick() {
      console.log('maxin handleClick');
    }
  },
}
const app = Vue.createApp({
  data() {
    return { number: 1 }
  },
  created() {
    console.log('created');
  },
  components: ['child'],
  mixins: [ myMixin ],
  methods: {
    handleClick() {
      console.log('handleClick');
    }
  },
  template: `
    <div>
      <div>{{number}}</div>
      <child />
      <button @click="handleClick">增加</button>
    </div>
  `
})
app.component('child', {
  mixins: [ myMixin ],
  template: '<div>{{count}}</div>'
})
const vm = app.mount('#root')

1.4 全局 mixin

不推荐使用

const app = Vue.createApp({
  data() {
    return { number: 1 }
  },
  created() {
    console.log('created');
  },
  components: ['child'],
  // mixins: [ myMixin ],
  methods: {
    handleClick() {
      console.log('handleClick');
    }
  },
  template: `
    <div>
      <div>{{number}}</div>
      <child />
      <button @click="handleClick">增加</button>
    </div>
  `
})
app.mixin({
  data() {
    return { 
      number: 2,
      count: 2
    }
  },
  created() {
    console.log('mixin created');
  },
  methods: {
    handleClick() {
      console.log('maxin handleClick');
    }
  },
})
app.component('child', {
  // mixins: [ myMixin ],
  template: '<div>{{count}}</div>'
})

1.5 自定义属性、组件中的属性优先级高于 mixin 属性的优先级

  • 自定义属性通过 $options 获取
const myMixin = {
  number: 1
}
const app = Vue.createApp({
  number: 2,
  mixins: [myMixin],
  template: `
    <div>
      <div>{{this.$options.number}}</div>
    </div>
  `
})
const vm = app.mount('#root')

1.6 通过 app.config.optionMergeStrategies 变更混入规则

const myMixin = {
  number: 1
}
const app = Vue.createApp({
  number: 2,
  mixins: [myMixin],
  template: `
    <div>
      <div>{{this.$options.number}}</div>
    </div>
  `
})
app.config.optionMergeStrategies.number = (mixinVal, appValue) => {
  return mixinVal || appValue
}
const vm = app.mount('#root')

2 开发实现 Vue 中的自定义指令

  • directive

2.1 自定义全局指令

const app = Vue.createApp({
  template: `
    <div>
      <input v-focus />
    </div>
  `
})
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
})
const vm = app.mount('#root')

2.2 自定义局部指令

const directives = {
  focus: {
    mounted(el) {
      el.focus();
    }
  }
}
const app = Vue.createApp({
  directives,
  template: `
    <div>
      <input v-focus />
    </div>
  `
})
const vm = app.mount('#root')

2.3 自定义指令的生命周期

const app = Vue.createApp({
  template: `
    <div>
      <input v-focus />
    </div>
  `
})
app.directive('focus', {
  beforeMount() {
    console.log('beforeMount')
  },
  mounted(el) {
    el.focus()
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  },
  beforeUnmount() {
    console.log('beforeUnmount')
  },
  unmounted() {
    console.log('unmounted')
  },
})
const vm = app.mount('#root')

2.4 自定义指令传值 -- binding.value

const app = Vue.createApp({
  data() {
    return {
      top: 100
    }
  },
  template: `
    <div>
      <div v-pos="top" class="header">
        <input />
      </div>
    </div>
  `
})
app.directive('pos', {
  mounted(el, binding) {
    el.style.top = binding.value + 'px'
  }
})
const vm = app.mount('#root')

2.5 自定义指令简写

const app = Vue.createApp({
  data() {
    return {
      top: 100
    }
  },
  template: `
    <div>
      <div v-pos="top" class="header">
        <input />
      </div>
    </div>
  `
})
app.directive('pos', (el, binding) => {
    el.style.top = binding.value + 'px'
  },
)
const vm = app.mount('#root')

2.6 自定义指令绑定参数 -- binding.arg

const app = Vue.createApp({
    data() {
      return {
        distance: 100
      }
    },
    template: `
      <div>
        <div v-pos:left="distance" class="header">
          <input />
        </div>
      </div>
    `
  })
  app.directive('pos', (el, binding) => {
      el.style[binding.arg] = binding.value + 'px'
    },
  )
  const vm = app.mount('#root')

3 Teleport 传送门功能

  • 将元素挂载到其它元素节点上
<style>
  .area {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 200px;
    height: 200px;
    background: green;
  }
  .mask {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background: #000;
    opacity: 0.5;
    color: #fff;
    font-size: 100px;
  }
</style>
<body>
  <div id="root"></div>
  <div id="hello"></div>
</body>
<script>
  const app = Vue.createApp({
    data() {
      return {
        show: false,
        message: 'hello'
      }
    },
    methods: {
      handleClick() {
        this.show = !this.show
      }
    },
    template: `
      <div class="area">
        <button @click="handleClick">按钮</button>
        <teleport to="#hello">
          <div v-show="show" class="mask">{{message}}</div>
        </teleport>
      </div>
    `
  })
  const vm = app.mount('#root')
</script>

4 更加底层的 render 函数

  • template -> render -> h -> 虚拟DOM(js对象)-> 真实DOM -> 展示到页面上
const app = Vue.createApp({
  template: `
    <my-title :level="1">
      hello
    </my-title>
  `
})
app.component('my-title', {
  props: [ 'level' ],
  render() {
    const { h } = Vue;
    // 虚拟 DOM
    return h('h' + this.level, { name: '123' }, [
      this.$slots.default(),
      h('h4', {}, 'dell')
    ])
  }
  // template: `
  //   <h1 name="123" v-if="level=== 1"><slot /></h1>
  //   <h2 v-if="level=== 2"><slot /></h2>
  //   <h3 v-if="level=== 3"><slot /></h3>
  // `
})
const vm = app.mount('#root')

5 插件的定义和使用

  • plugin 插件,也是把通用性的功能封装起来
// 定义插件
const myPlugin = {
  install(app, options) {
    app.provide('name', 'dell luo')
    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: 'dell' })
const vm = app.mount('#root')

6 数据校验插件开发实例

  • 推荐使用 plugin,能够直观地体现出校验器的定义;不推荐只使用 mixin
const app = Vue.createApp({
  data() {
    return { name: 'dell', age: 23 }
  },
  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')
posted on 2022-03-16 11:38  pleaseAnswer  阅读(206)  评论(0编辑  收藏  举报