简体   繁体   English

Vue3- [Provide and Inject] 当数据改变时,不做视觉更新,我使用 filter( ) 删除数组中的一个项目

[英]Vue3- [Provide and Inject] when data changes ,not do visual update ,I use filter( ) to del an item in array

I am test provide and inject method.我正在测试provide and inject方法。 I put datas , del-function in parent to provide, I put dynamic render in child using v-for='data' in datas ...我将datasdel-function放在 parent 中以提供,我在 datas 中使用v-for='data' in datas将 dynamic render 放在 child ...

The goal I want to implement is: when I press the "delete button"=> del-function in child, then datas in parent get an item deleted, and datas in parent provide get updated.我要实现的目标是:当我在子项中按下“删除按钮”=> del-function时,父项中的datas被删除,父项中provide datas被更新。

Then child get new datas to do visual update.然后孩子获取新datas进行视觉更新。 v-for re-render. v-for重新渲染。 [!!!] [!!!]

But when I press the "delete button", datas updated,but visually,no one get deleted.但是当我按下“删除按钮”时, datas更新了,但从视觉上看,没有人被删除。

v-for rendered cards v-用于渲染的卡片

// parent vue file 
<template>
  <Reslist/>
</template>

<script>

import Reslist from './components/ResList.vue'

export default {
  name: "App",
  components: {
     Reslist
  },
  provide() {
    return {
      datas: this.datas,
      delData: this.delData,
    };
  },
  data() {
    return {
      datas: [
        {
          id: 1,
          name: "wawa",
          age: "18",
        },
        {
          id: 2,
          name: "wmmmfwa",
          age: "1128",
        },
      ],
    };
  },
  methods: {
    delData(id) {
      console.log('delete-id ='+ id);
      const newDatas = this.datas.filter( element => element.id !== id);
      this.datas = newDatas;
      console.log( this.datas);

    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


// child vue file
<template>
   <div v-for='data in datas' :key="data.name">
        <h2>{{data.name}}</h2>
        <p>{{data.age}}</p>
        <button @click='delData(data.id)'>delete</button>
   </div>
</template>
<script>
export default {
    inject:['datas','delData']
}
</script>
<style scoped>
div{
    width: 18.75rem;
    margin: 1.25rem auto;
    border: solid 1px grey;
    padding: 1.25rem;
}
</style>

I know how to use prop to pass data to child.我知道如何使用道具将数据传递给孩子。 I just want to know why [provide and inject] don't work??我只想知道为什么 [provide and inject] 不起作用?? In [provide],I already [datas = this.datas], does my logic have mistakes?在[provide]中,我已经[datas = this.datas],我的逻辑有错误吗?

Good night, Bro!晚安,兄弟!

I found a solution using computed props...我找到了一个使用计算道具的解决方案......

Hope its helpful!希望它有帮助!

Parent Vue File父视图文件

<template>
  <Reslist/>
</template>

<script>
import Reslist from './ResList.vue'
import { computed } from '@vue/reactivity'
export default {
  name: "App",
  components: {
     Reslist
  },
  provide() {
    return {
      datas: computed(() => this.datas),
      delData: this.delData,
    };
  },
  data() {
    return {
      datas: [
        {
          id: 1,
          name: "wawa",
          age: "18",
        },
        {
          id: 2,
          name: "wmmmfwa",
          age: "1128",
        },
      ],
    };
  },
  methods: {
    delData(id) {
      console.log('delete-id ='+ id);
      const newDatas = this.datas.filter( element => element.id !== id);
      this.datas = newDatas;
      console.log(this.datas);
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Child File子文件

<template>
   <div v-for='data in datas' :key="data.name">
        <h2>{{data.name}}</h2>
        <p>{{data.age}}</p>
        <button @click='delData(data.id)'>delete</button>
   </div>
</template>
<script>
export default {
  inject:['datas','delData']
}
</script>
<style scoped>
div{
    width: 18.75rem;
    margin: 1.25rem auto;
    border: solid 1px grey;
    padding: 1.25rem;
}
</style>

Configuring Main.js To Accept Computed prop.配置 Main.js 以接受 Computed 道具。

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.config.unwrapInjectedRef = true
app.mount('#app')

The information for this config: https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity此配置的信息: https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity

Your injected data is not working in a reactive way, and per the Vue.js Documentation , in order for injected data to do this, you must provide it as a computed property by wrapping it in a computed() function:您注入的数据没有以反应方式工作,并且根据Vue.js 文档,为了让注入数据执行此操作,您必须通过将其包装在computed() function 中将其作为计算属性提供:

在此处输入图像描述

Which states:其中指出:

Working with Reactivity使用反应性

In order to make injections reactively linked to the provider, we need to provide a computed property using the computed() function为了使注入反应性地链接到提供者,我们需要使用 computed() function 提供一个计算属性

In your case, it might look like this:在您的情况下,它可能看起来像这样:

  provide() {
    return {
      datas: computed(() => this.datas),
      delData: this.delData,
    };
  },

Having said this, Vue is always undergoing updates, enhancements and fixes, and in order for this to work fully, temporarily , you must add an additional config to your application:话虽如此,Vue 始终在进行更新、增强和修复,为了使其完全正常工作,暂时,您必须向您的应用程序添加额外的配置:

在此处输入图像描述

Which states:其中指出:

Temporary Config Required需要临时配置

The above usage requires setting app.config.unwrapInjectedRef = true to make injections automatically unwrap computed refs.上述用法需要设置app.config.unwrapInjectedRef = true以使注入自动解包计算的引用。 This will become the default behavior in Vue 3.3 and this config is introduced temporarily to avoid breakage.这将成为 Vue 3.3 中的默认行为,临时引入此配置以避免损坏。 It will no longer be required after 3.3. 3.3 之后将不再需要它。

In code, this could look like so:在代码中,这可能看起来像这样:

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

const app = createApp(App);
app.config.unwrapInjectedRef = true;

app.mount('#app')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM