为什么Vue中的模板渲染触发器在数组项属性和计算数组项属性之间存在差异?

ahy6op9u  于 6个月前  发布在  Vue.js
关注(0)|答案(1)|浏览(53)

根据建议,当“* prop作为需要转换的原始值传入 *"时,我试图“ Package ”原有的价值观(在我的例子中是数组),并使用计算prop中所需的任何额外属性进行扩展。但是-无论它是作为prop传递还是组件自己的数据-我发现计算数组中的项的属性的行为并不相同。
即使我在添加/修改数组项属性时使用Vue.set(),如果它直接在data/props上完成,它也会像预期的那样工作,模板会被渲染。但是当在计算数组上使用同样的方法时,模板不会更新,尽管对象的属性确实在后台更新了。
在下面找到一个简单的复制(只使用两个项目来展示它是一个数组,但如果数组中只有一个项目,示例也是一样的):

<html>
<div id="app">
  <div>
    based on yolodata:
    <div v-for="y in yolodata" :key="y.name + y.wtf">
      {{y.wtf}}
      <button @click="yoloclick(y)">yolobtn</button>
    </div>
    <br>
    based on yolocomputed:
    <div v-for="y in yolocomputed" :key="y.original.wtf + y.wtf">      
      {{y.wtf}}
      <!-- {{y.original.wtf}} if this is uncommented, it re-renders when original is updated, but when only referenced in the :key, it does not -->
      <button @click="yoloclick(y)">yolobtn</button>
    </div>
    <br>
    actual yolodata:
    <div id="actualdata"></div>
    actual yolocomputed:
    <div id="actualcomputed"></div>
    <br>
    console:
    <div id="console">{{console}}</div>
  </div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script>
  new Vue({
    el: '#app', //Tells Vue to render in HTML element with id "app"
    data: function(){
      return{
        yolodata: [{name: 'yolo1', wtf:'wtf1'},{name: 'yolo2', wtf: 'wtf2'}],
        console: ''
      }
    },
    computed:{
      yolocomputed(){   
        console.log('yolocomputed evaluated')
        //eslint-disable-next-line   
        this.console += 'yolocomputed evaluated\n'
        return this.yolodata.map(y => ({original: y, wtf: 'wtf'}))
      }
    },
    methods:{
      yoloclick(item){
        this.$set(item, 'wtf', item.wtf + 'X')
        document.getElementById('actualdata').innerHTML = JSON.stringify(this.yolodata)
        document.getElementById('actualcomputed').innerHTML = JSON.stringify(this.yolocomputed)
      },
    },
  });
</script>
</html>

字符串
计算属性本身只计算一次,这是正确的,因为它唯一的直接依赖是yolodata,它永远不会被修改,只有它内部的项的属性。(前两个按钮中的任何一个),第一次渲染都可以正常工作,在“实际”部分,您可以看到对象序列化,包括显示新值的computed属性(因为原始项是通过引用存储的,所以很有意义)。
但是第二个for循环渲染似乎关闭了,即使在for循环中从原始项中获得值:key,它也不会更新。(se评论行),然后它就这样做了,这对我来说已经是我不太明白的事情了。我知道这是一种欺骗vue强制重新渲染的方法,但为什么它在:键中使用时不适用呢?
如果直接在计算数组中使用Vue.set()修改项目,当序列化时,很明显对象已经改变了,我希望第二个for循环相应地更新,因为y.wtf直接在模板中引用,但是它什么也不做。只有当我再次修改原始数组中的某些内容时,它才会被渲染/更新-> vue看到computed属性的依赖项以某种方式发生了变化(?),即使数组本身没有发生变化-但只做一次。之后,即使我不断更新原始数组中的项目,computed属性的呈现也不会做任何事情。
我确实阅读了相关的Vue文档,但没有找到任何确切的细节来解释。据我所知,在这两种情况下,数组中的元素的属性都是使用Vue.set()修改的,所以它在这两种情况下都应该是React式的。
简而言之,我试图实现的正是Vue文档中所建议的,使用data/props作为原始默认值,并在计算属性中使用所需的额外内容来“装饰”它,而不是直接改变它(在示例中,为了简单起见,我使用了简单的数据而不是props,但这并没有改变任何东西)。在这种情况下,当我们谈论的是一个项目数组,而不是一个单一的prop,是我遗漏了什么,还是这只是因为我还没有得到支持的原因?

kyks70gy

kyks70gy1#

不同的是,computed是浅React的,只要正确使用,这不会导致问题。在这种情况下,yolocomputedyoloclick中发生了变化,这不是正常的用法。
计算通常可以通过React数据和观察器的组合来实现,这就是这里需要做的,deep选项取决于预期的行为:

data() {
  return{
    yolodata: [...],
    yolodatacopy: null
  },
},
watch: {
  yolodata: {
    immediate: true,
    deep: true,
    handler(new) {
      this.yolodatacopy = new.map(...);
    }
    ...

字符串

相关问题