Vue3 依赖注入------父级组件与子孙级组件之间的数据传递

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue3 依赖注入------父级组件与子孙级组件之间的数据传递相关的知识,希望对你有一定的参考价值。

参考技术A 依赖注入是针对 父级组件与子孙级组件之间的数据传递 数据的传递,或者有很多后代组件的情况,只针对直系后代使用,实现组件之间的数据共享。

需要使用到vue提供的 provide以及inject 方法

其中,provide用来提供传递的数据,inject用来接收数据

子组件的如果也想要使用爷爷组件的数据,操作方法是一样的,也是通过inject进行接收并且return,然后直接使用即可。

总结:

1.父传子孙数据:provide

2.子孙得到数据:inject

这里还是使用provide和inject来进行数据的传递,但是这次是通过函数的参数进行传值。

1.导入provide和inject到父组件中

2.通过provide声明函数,并要有形参用来接收孙组件传来的实参

总结:

1.孙子组件传递数据给爷爷组件,需要通过provide一个函数的方式实现

2.爷爷组件传递一个函数,后续通过函数的形参获取数据

孙子组件获取并调用该函数传递数据

1.父子传参:

爹给儿子传递数据,通过 自定义属性 ,给组件props属性,然后绑定在父组件的子组件上

儿子给爹传递数据,通过 自定义事件

2.爷爷孙子传参:

孙子给爷爷传值是 函数 ,通过provide一个函数,在孙子组件inject注入,然后通过参数传递想要传递的值

爷爷给子孙传递 数据 ,通过provide一个变量和值,在孙子组件inject注入,孙子组件通过inject接收数据即可。

3.后代给前辈 传数据都需要 函数传参

4.自定义属性、事件(函数)一般都绑定在父组件中,也就是provide一般出现在父组件,不论是提供给孙组件的数据还是接收孙组件数据的函数

Vue补充

1.vue中inject与provide的用法

provide/inject提供了一种新的组件间通信的方法。它允许父组件向子孙组件间进行跨层级的数据分发,但是provide/inject是非响应式的。一般用于子组件调用父组件的共有方法。它们两个需要一起使用,允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

实例如下:

Test.vue:

<template>
  <div class="about">
    <h1>我是父组件:{{msg}}</h1>
    <button @click="changeMsg">点位改变</button>
    <test2></test2>
  </div>
</template>

<script>
import test2 from "./Test2";
export default {
  name: "Test",
  data() {
    return {
      msg: "你好啊"
    };
  },
  //给子组件传递数据和方法
  provide() {
    return {
      msg: this.msg,
      messageBox:this.messageBox
      
    };
  },
  components: {
    test2
  },
  methods: {
    changeMsg() {
      this.msg = "今天天气转暖";
    },
    messageBox(msg){
      alert(msg)
    }
  }
};
</script>

<style>
</style>

Test2.vue:

<template>
  <div><h3>我是子组件</h3>{{msg}}
  <button @click="message">我要执行父组件的方法</button>
  </div>
</template>

<script>
export default {
    name:‘Test2‘,
    //接收父组件的数据
    inject:[‘msg‘,‘messageBox‘],
    methods:{
        message(){
            this.messageBox(‘我是子组件‘)
        }
    }
   
}
</script>

<style>

</style>

当点击父组件中的按钮时,父组件中的msg已经改变,但是子组件中接收的数据并未发生变化。这就说明这种方式共享数据不是响应式的,一般不使用这种方式传递数据。
当点击子组件中的按钮时,会执行父组件的messageBox方法,是推荐的用法。

2.vue.nextTick()用法

在下次 DOM 数据更新循环结束之后执行延迟回调。也就是说此回调函数是延迟执行的,是在下一次DOM数据更新后自动执行。
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。主要用在两方面,一种是在vue的created函数中操作DOM数据时使用,另一种是修改DOM数据后获取最新的DOM数据。

2.1在vue的created函数中操作DOM数据时使用

<template>
  <div>
    <span ref="span">你好</span>
  </div>
</template>

<script>
export default {
  name: "Hello",
  created() {
    //在DOM再次更新后执行此回调函数
    this.$nextTick(() => {
      this.$refs.span.innerHTML = "今天加班";
    });
  },
};
</script>

<style>
</style>

2.2修改DOM数据后获取最新的DOM数据

<template>
  <div>
    <button id="firstBtn" @click="testClick()" ref="aa">{{msg}}</button>
  </div>
</template>

<script>
export default {
  name: "Hello",
  data() {
    return {
      msg: "old"
    };
  },
 
  methods: {
    testClick() {
      //点击按钮修改数据
      this.msg = "new";
      console.log(this.$refs.aa.innerText); //输出:old
      //此时数据并没有更新,原因是DOM没有更新

      //此时数据更新了,原因是在输出的时候DOM已经更新了
      this.$nextTick(() => {
        console.log(this.$refs.aa.innerText); //输出:new
      });
    }
  }
};
</script>

<style>
</style>

3.使用vue的表单方式自定义验证方法进行验证

在验证的时候,除了el-form自带的验证规则外,还可以自己进行验证,然后在规则中指定验证的方法即可。如自定义手机号验证,不管验证是否通过,必须返回一个callback对象。代码如下:

<template>
  <el-form
    :model="ruleForm"
    :rules="rules"
    ref="ruleForm"
    label-width="100px"
    class="demo-ruleForm"
  >
    <el-form-item label="用户名" prop="name">
      <el-input v-model="ruleForm.name"></el-input>
    </el-form-item>
    <el-form-item label="角色" prop="role">
      <el-select v-model="ruleForm.role" placeholder="请选择角色">
        <el-option label="学生" value="0"></el-option>
        <el-option label="教师" value="1"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="爱好" prop="hobby">
      <el-checkbox-group v-model="ruleForm.hobby">
        <el-checkbox label="0" name="hobby">跑步</el-checkbox>
        <el-checkbox label="1" name="hobby">打篮球</el-checkbox>
        <el-checkbox label="2" name="hobby">踢足球</el-checkbox>
        <el-checkbox label="4" name="hobby">听音乐</el-checkbox>
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="性别" prop="sex">
      <el-radio-group v-model="ruleForm.sex">
        <el-radio label="0">男</el-radio>
        <el-radio label="1">女</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="手机号" prop="phone">
      <el-input v-model="ruleForm.phone"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(‘ruleForm‘)">保存</el-button>
      <el-button @click="resetForm(‘ruleForm‘)">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: "FormValidate",
  data() {
    //自定义验证规则,在rules中使用
    //手机号验证
    let phoneValidate = (rule, value, callback) => {
      let phoneReg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
      if (!value) {
        //如果为空就回调错误的信息
        return callback(new Error("手机号不能为空"));
      }
      if (!phoneReg.test(value)) {
        callback(new Error("手机格式不正确"));
      } else {
        //这个必须要调用来放行
        callback();
      }
    };
    return {
      ruleForm: {
        hobby: []
      },
      rules: {
        name: [
          { required: true, message: "请输入姓名", trigger: "blur" },
          { min: 2, max: 5, message: "长度在 2 到 5 个字符", trigger: "blur" }
        ],
        role: [{ required: true, message: "请选择角色", trigger: "change" }],
        hobby: [
          {
            type: "array",
            required: true,
            message: "请至少选择一个爱好",
            trigger: "change"
          }
        ],
        sex: [{ required: true, message: "请选择性别", trigger: "change" }],
        phone: [{ required: true, validator: phoneValidate, trigger: "blur" }]
      }
    };
  },
  methods: {
    //提交验证
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          alert(JSON.stringify(this.ruleForm));
          //清除表单验证规则
          this.$refs[formName].clearValidate()
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
};
</script>

<style>
</style>

4.vue filters中使用data中数据

vue 的filters中 this指向的并不是vue实例,但想要获取vue实例中data中的数据,可以在 beforeCreate中将vue实例赋值给定义的全局变量app,然后在filters中通过app代替this来获取data中的数据。

<template>
    <div>
        <div v-for="(item,index) in list" :key="index">
            <p>姓名{{item.name}}</p>
            <p>性别{{item.sex | sexFilter}}</p>
        </div>
    </div>
</template>

<script>
    let vueApp = null
    export default {
        name: ‘UserFilters‘,
        data() {
            return {
                sexOption: [{
                    label: ‘男‘, value: 0
                }, {
                    label: ‘女‘, value: 1
                }],
                list: [{
                    name: ‘张三‘,
                    sex: 0
                }, {
                    name: ‘李四‘,
                    sex: 1
                }]
            }
        },
        filters: {
            //性别过滤显示
            sexFilter(data) {
                let resultData = ‘‘
                vueApp.sexOption.forEach(element => {
                    if (element.value == data) {
                        resultData = element.label
                    }
                });
                return resultData
            }
        }
    }
</script>

<style scoped>

</style>

.

 

以上是关于Vue3 依赖注入------父级组件与子孙级组件之间的数据传递的主要内容,如果未能解决你的问题,请参考以下文章

vue3如何进行数据依赖注入provide/inject

Button按钮--inject与provide

vue 提供注入 provideinject 深层嵌套通信

Vue.js - 父级基于无渲染子数据生成组件

第十讲、Vue3.x父组件给子组件传值、Props、Props验证、单向数据流

Vue补充