工作中常用的Vue技巧

1.实现跨层组件通信

重温一下常用的父子组件通信方法:

 //父组件
 <template>
   <my-header :title="title" @changeTitle="changeTitle"></my-header>
 </tempale>
 <script>
   import myHeader from "@/components/Header.vue"; //引入组件
   export default {
   data(){
    return{
     title:"父传子测试"
    }
   },
   components:{ 
     "my-header":myHeader  
    },
    methods:{
      changeTitle(val){
       this.title = val
      }
    }
   }
 </script>
 
 //子组件 myheader.vue
 <template>
   <h1>{{ title }}</h1>
   <button @click="triggerMethod">触发父组件方法</button>
 </tempalte>
 <script>
  export default{
     props: {//接收父组件出来的title
        title:{
         type: String,
         default: ""
        }
     }, 
     methods:{
      triggerMethod:function(){
       this.$emit("changeTitle","传参数");  //子组件通过$emit 与父组件通信  
      }
     }
  }
 </script>
 
复制代码

provide/inject(提供/注入),可以实现跨层组件(祖孙)间通信,不需要将数据一层一层向下传递。

//父组件 Father.vue
<template>
  <son></son>
</template>
<script>
 import { defineComponent, reactive, provide, computed } from "vue";
 import son from "@/components/Son";
 export default defineComponent({
  components: {
    son
  },
  setup() {
   let params = reactive({
      name: "来自父亲的参数"
   })
   provide("name", computed(()=> params.name)); //用计算属性返回值能够动态传递来子/孙组件(当子孙组件通过方法触发修改name值时)
   function changeName(val){
     params.name = val; //子孙组件触发
   }
   provide("changeName",changeName);
  }
 })
</script>
复制代码
//儿子组件 Son.vue
<template>
  <h2>{{ name }}</h2>  
  <button @click="changeName('儿子组件触发')">儿子组件触发Name修改</button>
  <div class="grandson">
    <grandson></grandson>
  </div>
</template>
<script>
import grandson from "@/components/grandson";
import { defineComponent, inject } from "vue";
export default defineComponent({
  components: { grandson },
  setup() {
    let name = inject("name");  //接收Father组件传来的name
    let changeName = inject("changeName"); //接收方法
    return {
      name,
      changeName,
    };
  },
});
</script>
复制代码
//孙子组件 grandson.vue
<template>
  <h2>{{ name }}</h2>
  <button @click="changeName('孙子组件触发')">孙子组件触发Name修改</button>
</template>
<script>
import { defineComponent, inject, watch } from "vue";
export default defineComponent({
  name: "HelloWorld",
  setup() {
    let name = inject("name");
    let changeName = inject("changeName");
    watch(name,(newValue,oldValue)=>{
      //这里可以监听name的变化
    })
    return {
      name,
      changeName,
    };
  },
});
</script>
复制代码

效果:子孙组件都接收到Father组件传来的参数"来自Father组件的参数"。

image.png

动态gif:当点击儿子组件或者孙子组件按钮时,触发changeName事件在Father组件上修改name值。

result1.gif

2.自动化批量引入模块

日常开发中经常会遇到导入多个模块,每个都要import,很麻烦。

image.png

使用webpack的api,通过require.context函数获取一个特定的上下文,实现自动化导入模块功能。
require.context(directory, useSubdirectories = false, regExp = /^.//);

image.png

  //1.directory {String} -读取文件的路径 
//2.useSubdirectories {Boolean} -是否遍历文件的子目录
//3.regExp {RegExp} -匹配文件的正则

let moduleFiles = require.context('../model', false, /\.js$/)
let res = {};
moduleFiles.keys().map(path => {
  let methods = moduleFiles(path);
  console.log(methods)
  Object.keys(methods).forEach(key => {
    if (key === "default") {
      res[methods[key].name] = methods[key];
    } else {
      res[key] = methods[key];
    }
  })
})

export default res
复制代码

image.png

3.使用函数式组件

对于某些组件,如果我们只是用来显示一些数据,不需要管理状态、监听数据等。那么我们可以使用函数式组件代替传统组件。

//father.vue
<template>
  <child :name="name"></child>
</template>

// child.vue
<template functional>
  <div class="component">{{ props.name }}</div>  //通过props接收父组件的传参
</template>
复制代码

4. 优雅更新Props

//father.vue
<template>
  <div class="son">
    <son v-model:name="name"></son>  
  </div>
</template>

//son.vue
<template>
  <h2>{{ name }}</h2>
  <button @click="changeName('儿子组件触发')">儿子组件触发Name修改</button>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
  props: {
    name: String,
  },
  setup(props) {
    function changeName(val) {
      this.$emit("update:name", val); //不需要再通过触发父组件的方法修改
    }
    return {
      changeName,
    };
  },
});
</script>
复制代码

vue2.x 这样写<son :name.sync="name"></son>
vue3.x 详情参考官方文档 v3.cn.vuejs.org/guide/migra…

image.png

5.Vue3实现兄弟组件通信

Vue3移除了 $on$off 和 $once 方法。$emit 仍然包含于现有的 API 中,因为它用于触发由父组件声明式添加的事件处理函数。官方推荐: 事件总线模式可以被替换为使用外部的、实现了事件触发器接口的库,例如 mitt 或 tiny-emitter
详情:v3.cn.vuejs.org/guide/migra…

 //eventBus.js
 import Emitter from 'tiny-emitter'
 const emitter = new Emitter();
 export default {
   $on: (...args) => emitter.on(...args),
   $once: (...args) => emitter.once(...args),
   $off: (...args) => emitter.off(...args),
   $emit: (...args) => emitter.emit(...args),
 }
复制代码
//兄弟组件1
import emitter from "@/assets/eventBus";
 setup() {
    emitter.$on("some-event", (...arg) => {
      console.log(arg);
    });
  }
  
//兄弟组件2
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <button @click="triggerSiblingMethod">触发兄弟组件</button>
  </div>
</template>
<script>
import { defineComponent } from "vue";
import emitter from "@/assets/eventBus";
export default defineComponent({
  setup() {
    function triggerSiblingMethod() {
      emitter.$emit("some-event", "value1", "value2", 3);
    }
    return {
      triggerSiblingMethod,
    };
  },
});
</script>
复制代码

点击兄弟组件2的按钮后,兄弟组件1输入下面信息。
image.png

Guess you like

Origin juejin.im/post/7021057406167679006