为啥如果我得到计算对象中的对象属性未定义而不是对象本身?哪种方法更适合这种情况?

Posted

技术标签:

【中文标题】为啥如果我得到计算对象中的对象属性未定义而不是对象本身?哪种方法更适合这种情况?【英文标题】:Why if I get the object property within the computed object gets undefined but not the object itself? Which approach fits better in this context?为什么如果我得到计算对象中的对象属性未定义而不是对象本身?哪种方法更适合这种情况? 【发布时间】:2021-03-01 18:10:22 【问题描述】:

我的问候。

在上下文中,我提出这个问题的目的是能够根据 <app-selector> Vue 组件的选定选项在表单内呈现子组件,就这么简单和愚蠢。

为了简单起见。我在这里做了一个 sn-p 来暴露我想要弄清楚的东西。 基本上,目的是通过使用计算属性cardTypeComponent 来获取要呈现的组件名称。但是,我想了解cardTypeComponent 的工作方式,因为一方面我不明白为什么第一个返回(return this.form)给对象(this.form)提供了我想要的属性(card_type ) 但另一方面,第二个返回 (return this.form.card_type ? this.form.card_type + 'Compose' : '') 给了我一个空字符串,假设 this.form.card_typeundefined,当很清楚第一个返回时,事实上,并没有把它当作 @987654331 @。

有更多的上下文,因为一旦选择了选项,在设置 this.form 对象内的值之前,服务器会进行验证过程。此外,表单交互是通过步骤进行的,因此一旦用户选择了选项,他必须单击一个按钮才能到达与所选类型卡对应的表单字段,因此该组件不会在用户第一时间呈现选择一个选项,就像在 sn-p 方法中一样。但是,它会纠缠我的要求。先谢谢了。

最好使用下面的 Fiddle 链接。

片段

var appSelector = Vue.component('app-selector', 
  name: 'AppSelector',
  template: `<div>
               <label for="card_type">Card Type:</label>
               <select :name="name" value="" @change="sendSelectedValue">
                 <option v-for="option in options" :value="option.value">
                   option.name 
                 </option>
           </select>
             </div>`,
  props: 
    name: 
      required: false,
      type: String,
    ,
    options: 
      required: false,
      type: Array,
    
  ,
  methods: 
    sendSelectedValue: function(ev) 
      this.$emit('selected', ev.target.value, this.name)
    
  
);

var guessByImageCompose = Vue.component(
  name: 'GuessByImageComponse',
  template: `<p>Guess By Image Compose Form</p>`
);

var guessByQuoteCompose = Vue.component(
  name: 'GuessByQuoteComponse',
  template: `<p>Guess By Quote Compose Form</p>`
);

new Vue(
  el: '#app',
  components: 
    appSelector: appSelector,
    guessByImageCompose: guessByImageCompose,
    guessByQuoteCompose: guessByQuoteCompose,
  ,
  data() 
    return 
      form: ,
      card_types: [
        
          name: 'Guess By Quote',
          value: 'GuessByQuote'
        ,
        
          name: 'Guess By Image',
          value: 'GuessByImage'
        
      ],
    
  ,
  computed: 
    cardTypeComponent: function() 
        return this.form; // return  card_type: "GuessByImage" || "GuessByQuote" 
        return this.form.card_type ? this.form.card_type + 'Compose' : ''; // return empty string ("") Why?
    
  ,
  methods: 
    setCardType: function(selectedValue, field) 
      this.form[field] = selectedValue;
      console.log(this.form.card_type); // GuessByImage || GuessByQuote
      console.log(this.cardTypeComponent); // empty string ("") Why?
    
  ,
  mounted() 
    console.log(this.cardTypeComponent); // empty string ("")
  
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <form action="#" method="post">
    <app-selector
      :name="'card_type'" 
      :options="card_types"
      @selected="setCardType"
    >
    </app-selector>
     cardTypeComponent  <!-- Always empty string !-->
    <component v-if="cardTypeComponent !== ''" :is="cardTypeComponent">
      
    </component>
  </form>
</div>

https://jsfiddle.net/k7gnouty/2/

【问题讨论】:

【参考方案1】:

您正在为this.form 设置一个属性,该属性未首先在data 中初始化。这意味着你遇到了 Vue 的change detection caveat。设置时使用Vue.set

methods: 
  setCardType: function(selectedValue, field) 
    Vue.set(this.form, field, selectedValue);
  

或者,如果对您更有效,您可以先声明属性。

【讨论】:

我想念这个警告,它有效。我将有多种卡片类型可供选择,每种卡片都有自己的字段,所以我认为动态设置属性可能更合适,因为会有一堆不同的字段,因此数据太多初始化,但如果它不打扰您,我想知道您对此的看法。 是的,没关系。在某些情况下,我更喜欢使用Vue.set。例如,假设您使用一个对象来跟踪数百个 div 可见性,无论 div 是显示还是隐藏。在这种情况下,Vue.set 更有意义。

以上是关于为啥如果我得到计算对象中的对象属性未定义而不是对象本身?哪种方法更适合这种情况?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我得到 null 而不是 Map 对象?如何解决这个问题?

Vue / Vuex:双向计算属性 - 未定义不是重新加载的对象

Angular - 为啥我得到对象而不是对象数组?

为啥同一类而不是同一对象可以访问受保护和私有属性?

为啥这个 Vue 计算属性不是响应式的?

为啥我的 Dart 构造函数返回的是动态对象而不是类型对象?