当前位置: 首页 > 知识库问答 >
问题:

vue.js - 如何在 Vue 选项式 API 中使用 provide 实现基本数据类型的双向数据传输?

池麒
2024-07-04

我有两个组件,我想通过provide一个响应式对象实现父子之间的双向数据传输,但是我发现对象类型可以正确实现响应式,但是基本数据类型无法实现,请问这是为什么?
我个人的猜想是选项式的api会对基本数据类型触发自动解包,但是setup函数里面不会触发,因此造成了不一致的问题。

//父组件
<script>
import Child from './Child.vue'
import { computed } from 'vue'

export default {
  components: { Child },
  data() {
    return {
      message: {"name":"hello"},flag:false
    }
  },  methods:{
change()
{
  this.flag=!this.flag
}
  },
  provide() {
    return {
      message: this.message,flag:this.flag
    }
  }
}
</script>

<template>
  <div>
    <input v-model="message.name">
    <button @change="change">click</button>     
    {{ flag}}
  </div>
  <Child />
</template>
//子组件
<script>

export default {
  inject:["message","flag"],
  methods:{
change()
{
  this.flag=!this.flag
}
  }
}
</script>

<template>
  <div>
  <input v-model="message.name">
  <button @change="change">click</button>   
      {{ flag}} 
  </div>

</template>

尝试:我查阅官方文档发现data返回的都是响应式对象,并且使用setup函数传递基本数据类型可以正确传递.
预期结果:使用选项式的provide传递基本数据类型时可以实现双向绑定

共有2个答案

归德厚
2024-07-04

我一般会通过 provide 暴露出来两个函数,而不是直接暴露原本的响应式对象给子级来直接修改。

一个函数是获取响应式对象的函数,一个是给响应式对象更新的函数。
举个例子:

<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'

const location = ref('North Pole')

provide('location', {
  getLocation: () => location,
  updateLocation: (newValue) => location.value = newValue
})
</script>
<!-- 在注入方组件 -->
<script setup>
import { inject, computed } from 'vue'

const { getLocation, updateLocation } = inject('location')

const location = computed(() => getLocation())
</script>

<template>
  <button @click="updateLocation('newValue')">{{ location }}</button>
</template>

不过我看现在 Vue3 最新的文档,已经不需要通过函数返回的方式,来保持 provide 变量的响应式了,那么就可以直接和文档中的一样这样写:

<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'

const location = ref('North Pole')

function updateLocation() {
  location.value = 'South Pole'
}

provide('location', {
  location,
  updateLocation
})
</script>
<!-- 在注入方组件 -->
<script setup>
import { inject } from 'vue'

const { location, updateLocation } = inject('location')
</script>

<template>
  <button @click="updateLocation">{{ location }}</button>
</template>

#和响应式数据配合使用 依赖注入 | Vue.js

小牛23066
2024-07-04

在 Vue 的选项式 API 中,provideinject 主要用于依赖注入,它们并不直接支持基本数据类型的双向绑定。当你在 provide 方法中直接返回非响应式引用(比如基本数据类型 booleannumberstring 等)时,你其实是在传递一个值的副本,而不是对原始数据的引用。因此,当在父组件或子组件中修改这个值时,并不会影响到对方组件。

为了使用 provideinject 来进行基本数据类型的“双向数据传输”(注意这并不是真正的双向绑定,但可以实现类似的功能),你需要在 provide 中提供的是一个可以被修改的对象或响应式引用,而不是基本数据类型。

对于基本数据类型,你可以通过提供一个对象或响应式引用来封装它们,然后在父组件和子组件中修改这个对象的属性来实现类似的效果。

但是,对于你给出的代码示例,即使你尝试通过对象封装基本数据类型(如 flag),由于你直接在 provide 中返回了 this.flag 的值(一个基本数据类型的副本),它仍然不会按预期工作。

以下是一个修改后的示例,展示了如何使用一个响应式对象来封装基本数据类型,并通过 provideinject 在父子组件之间共享它:

// 父组件
<script>
import { reactive, toRefs } from 'vue';
import Child from './Child.vue';

export default {
  components: { Child },
  setup() {
    const state = reactive({
      message: { name: "hello" },
      flag: false
    });

    function changeFlag() {
      state.flag = !state.flag;
    }

    return {
      ...toRefs(state),
      changeFlag
    };
  },
  provide() {
    return {
      // 注意这里返回的是整个响应式对象
      // 或者,你也可以通过 `toRefs` 将状态分解为响应式引用并返回
      state: this.state
    };
  }
};
</script>

<template>
  <div>
    <input v-model="state.message.name">
    <button @click="changeFlag">click</button>
    {{ state.flag }}
  </div>
  <Child />
</template>
// 子组件
<script>
export default {
  inject: ["state"],
  methods: {
    changeFlag() {
      this.state.flag = !this.state.flag;
    }
  }
};
</script>

<template>
  <div>
    <input v-model="state.message.name">
    <button @click="changeFlag">click</button>
    {{ state.flag }}
  </div>
</template>

在这个修改后的示例中,我们使用了 Vue 3 的 setup 函数和 reactive API 来创建一个响应式状态对象。然后我们使用 provide 来共享这个状态对象,并在父组件和子组件中都通过 inject 来接收它。现在,当我们修改 state.flag 时,无论是在父组件还是子组件中,都会影响到另一个组件。

 类似资料:
  • 本文向大家介绍Vue实现双向数据绑定,包括了Vue实现双向数据绑定的使用技巧和注意事项,需要的朋友参考一下 Vue实现双向数据绑定的方式,具体内容如下 Vue是如何实现双向数据绑定的呢?答案是前端数据劫持。其通过Object.defineProperty()方法,这个方法可以设置getter和setter函数,在setter函数中,就可以监听到数据的变化,从而更新绑定的元素的值。 实现对象属性变化

  • 本文向大家介绍Vue.js中provide/inject实现响应式数据更新的方法示例,包括了Vue.js中provide/inject实现响应式数据更新的方法示例的使用技巧和注意事项,需要的朋友参考一下 vue.js官方文档:https://cn.vuejs.org/v2/api/#provide-inject 首先假设我们在祖辈时候传入进来是个动态的数据,官方不是说如果你传入了一个可监听的对象,

  • 变量只是用于存储值的保留内存位置。 这意味着当您创建变量时,您会在内存中保留一些空间。 根据变量的数据类型,操作系统分配内存并决定可以存储在保留内存中的内容。 因此,通过为变量分配不同的数据类型,可以在这些变量中存储整数,小数或字符。 Java中有两种数据类型 - 原始数据类型 参考/对象数据类型 原始数据类型 Java支持八种原始数据类型。 原始数据类型由语言预定义,并由关键字命名。 现在让我们

  • 着色器语言GLSL的基本数据类型和C语言一样具有常见的整型数int、浮点数float和布尔值bool类型数据。 关键字 数据类型 值 bool 布尔值 布尔变量值为true或false int 整型数 值为整数,比如0,1,2,3... float 单精度浮点数 浮点数用小数点表示,比如0.6,3.14,2.8 // bool关键字声明一个数据类型是布尔值的变量,并赋值为true bool lig

  • 在之前的 JavaScript 基础文章中(编号 02、编号 07),我们介绍过,变量有以下数据类型: 基本数据类型(值类型):String 字符串、Number 数值、Boolean 布尔值、Null 空值、Undefined 未定义。 引用数据类型(引用类型):Object 对象。 本文,我们针对这两种类型,做个详细介绍。我们先来看个例子。 基本数据类型举例: var a = 23;

  • 1. 前言 本小节我们将介绍 Vue 中数据的双向绑定指令 v-model。v-model 的学习相对简单 我们可以用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。 2. 慕课解释 用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选