Vue 自定义插件等知识点(笔记自用,测试代码基于vue 3)

目录

1. provide,inject 依赖注入

2.directive 自定义指令

3.plugin 自定义插件 install,app.use()

4 .teleport 把组件某些元素直接挂到其他dom元素上

5.Non-Props 特性


1. provide,inject 依赖注入

当父组件要向后代组件传递参数的时候,要一层一层定义 props 传递,比较繁琐

<script>
    const app = Vue.createApp({
      data() {
        return {
          count: 1
        }
      },
      template:`
        <div>
          <child :count="count"/>
        </div>
      `
    })
    
    app.component('child',{
      props:['count'],
      template:`
        <div>
          子组件{
   
   { count }}
          <child-child :count="count"/>
        </div>
      `
    })

    app.component('child-child',{
      props:['count'],
      template: '<div>子-子组件{
   
   { count }}</div>'
    })
    const vm = app.mount('#root')
  </script>
  • provide / inject 
  • 父组件使用 provide 传递参数
  • 子组件使用 inject 接收即可
  • 但是父组件改变参数的时候,子组件值不会跟着变化,因为 provide 是一次性传递,不是双向绑定,后续学习有解决办法
<script>
    const app = Vue.createApp({
      data() {
        return {
          count: 1
        }
      },
      provide() {
        return {
          count: this.count
        }
      },
      template:`
        <div>
          父组件 {
   
   { count }}
          <child />
          <button @click="count++">+1</button> // 后代组件的 count 不会跟着改变
        </div>
      `
    })

    app.component('child',{
      inject: ['count'],
      template:`
        <div>
          子组件{
   
   { count }}
          <child-child />
        </div>
      `
    })

    app.component('child-child',{
      inject: ['count'],
      template: '<div>子-子组件{
   
   { count }}</div>'
    })
    const vm = app.mount('#root')
  </script>

2.directive 自定义指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
  <style>
    .header{
      position: absolute
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // 局部自定义指令
  const directives = {
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  }

  const app = Vue.createApp({
    data() {
      return {
        distence: 100
      }
    },
    directives: directives, // 局部自定义指令
    template: `
      <div>
        <div class="header" v-pos:right="distence">
          <input v-focus/>
        </div>
      </div>
    `
  });
  // 全局指令
  /* app.directive('pos', {
    mounted(el, binding) {
      el.style[binding.arg] = binding.value + 'px'
    },
    updated(el, binding) {
      el.style[binding.arg] = binding.value + 'px'
    },
  }) */
  // 以上写法可简化为:
  app.directive('pos', (el, binding) => {
    el.style[binding.arg] = binding.value + 'px'
  })

  const vm = app.mount('#root');
</script>
</html>

3.plugin 自定义插件 install,app.use()

  • 把通用的性能封装起来
  • app.config.globalProperties 扩展全局属性(vue 3)

 可封装provide,directive,mixin等

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 32</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    install(app, options) {
      app.provide('name', 'Dell Lee');
      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');
</script>
</html>

数据校验插件开发实例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 33</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // 对数据做校验的插件
  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) => {  //或是: install(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');
</script>
</html>

4 .teleport 把组件某些元素直接挂到其他dom元素上

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
  <style>
    .area{
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 200px;
      height: 300px;
      background-color: green;
    }
    .mask{
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      background-color: #000;
      opacity: 0.5;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data() {
      return {
        show: false
      }
    },
    template: `
      <div>
        <div class="area">
          <button @click="show = !show">点击</button> 
          <teleport to="body">
            <div v-show="show" class="mask"></div>
          </teleport>
        </div>
      </div>
    `,
    created() {
      console.log('app created')
    },
    mounted() {
    },
    methods: {
      handleClick() {
        console.log('app click')
      }
    }
  });
   
  const vm = app.mount('#root')
</script>
</html>

5.Non-Props 特性

  • 如果父组件传递的参数,子组件没有通过 props 接收,那么,参数会绑定在子组件的 dom 节点上
  • 不继承父组件传递的参数 inheritAttrs :false
  • 什么情况下使用 Non-Props 特性? 

     传递 style 样式或是 class 等属性

  • 当子组件有多个根节点,Non-Props 失效,使用 $attrs 将所有父组件传递的属性放到当前组件上

  • 拿到某一个属性 $attrs.属性值 

  • 也可以在其他生命周期函数或js方法里使用 this.$attrs

    ​​​​​

不继承父组件传递的参数 inheritAttrs :false 

  • 什么情况下使用 Non-Props 特性? 

        传递 style 样式或是 class 等属性

 当子组件有多个根节点,Non-Props 失效,使用 $attrs 将所有父组件传递的属性放到当前组件上

 ​​​​​​

拿到某一个属性 $attrs.属性值 

 也可以在其他生命周期函数或js方法里使用 this.$attrs

猜你喜欢

转载自blog.csdn.net/weixin_39763711/article/details/126528710