【问题标题】:Vue: "_" prefixed property not working in data propertyVue:“_”前缀属性在数据属性中不起作用
【发布时间】:2019-11-18 05:10:58
【问题描述】:

我正在尝试将计算属性设置为 Vue.js 中子组件的道具。

这是组件代码(Here's the full (not) working example)的摘录:

<div id="app">
  <show-me :title="aTitle"></show-me>
</div>
const ShowMe = {
  data() {
    return {
      _title: null
    }
  },
  computed: {
    title: {
      set: function(val) {
        this._title = val;
      },
      get: function() {
        return this._title;
      }    
    }
  },
  template: `
    <div>
      should display title: {{title}} <br/>
      but instead typeof title: {{typeof title}}
    </div>`
};

const vm = new Vue({
  el: '#app',
  data: {
    aTitle: 'A Title'
  },
  components: {
    'show-me': ShowMe
  }
});

在运行示例时,模板中组件的标题值未定义。它非常简单明了,我不明白为什么它不起作用。

【问题讨论】:

  • 看起来你的组件应该只需要定义一个title prop(即props: ['title'])。您不需要 _title 数据属性或 title 计算属性
  • 至于为什么使用计算属性:它是从更大的上下文中摘录的,这只会使示例复杂化。关于可重现的示例:我的问题中包含的 codepen 链接是否不起作用?又来了:codepen.io/mikekastner/pen/XWWoRZv
  • 在这种情况下,您的简化太过分了。就目前而言,您对计算属性的使用没有意义。是的,您的链接有效,但问题应包含所有必需的信息。见stackoverflow.com/help/how-to-ask
  • 我真诚地道歉,我以如此草率和轻率的方式发布了我的问题。它绝不是为了过于简单化,也不是为了没有意义。我真的很抱歉,我希望我能弥补我的错误。既然这是不可能的,剩下我要做的就是尝试在未来提出更好的问题并请求宽恕。
  • 无需道歉,很高兴您找到了合适的答案。

标签: javascript vue.js


【解决方案1】:

_ 前缀属性是为 Vue 的内部属性保留的。它们不可用于直接绑定(但您可以将它们绑定为 $data._message) - Evan You(Vue 创建者)

您不能使用 _ 前缀值,因为它在 vue 系统中被视为内部属性

参考 - https://github.com/vuejs/vue/issues/2098

Docs 中也提供了最恰当的解释 -

以 _ 或 $ 开头的属性不会在 Vue 上代理 实例,因为它们可能与 Vue 的内部属性和 API 方法。您必须以 vm.$data._property 的身份访问它们

https://vuejs.org/v2/api/#data

所以在你的情况下,你会用this.$data._title替换this._title

const ShowMe = {
  data() {
    return {
      _title: null
    }
  },
  computed: {
    title: {
      set: function(val) {
        this.$data._title = val;
      },
      get: function() {
        return this.$data._title;
      }    
    }
  },
  template: `
    <div>
      should display title: {{title}} <br/>
      but instead typeof title: {{typeof title}}
    </div>`
};

const vm = new Vue({
  el: '#app',
  data: {
    aTitle: 'A Title'
  },
  components: {
    'show-me': ShowMe
  }
});

【讨论】:

  • 您的组件上没有定义props,那么:title="aTitle" 绑定应该如何工作?
  • 感谢您指出问题。我已经相应地更改了示例,但它仍然无法正常工作(链接到 codepen):codepen.io/mikekastner/pen/RwwEgQY 现在我得到:TypeError:“this.$data is undefined”
  • @LongHike 你的data 函数需要返回一个对象
  • 正确 - 您更新的 sn-p 在您的数据属性中不包含 _title
  • @SatyamPathak 是的,你是对的,当然。但是,仍然收到“TypeError:“this.$data is undefined””
【解决方案2】:
const ShowMe = {
      props:{
        title:{
          type:String,
          required:true
        }
      },
      template: `
        <div>
          should display title: {{title}} <br/>
          but instead typeof title: {{typeof title}}
        </div>`
    };

或者你可以简单地使用如下

const ShowMe = {
          props:['title'],
          template: `
            <div>
              should display title: {{title}} <br/>
              but instead typeof title: {{typeof title}}
            </div>`
        };

【讨论】:

  • 您无法更改 OP 的实现结构。可能settersgetters 出于某种原因存在
  • @SatyamPathak 直到 OP 给出了他们需要计算属性的充分理由,这是正确的答案
  • @Phil - 可能但我更偏向于为什么给定的 sn-p 不起作用。谢谢指点
【解决方案3】:

此代码有效。避免使用this.$data 将是更一致的做法,尽管另一个答案是正确的,因为您当然可以使用它。最好完全避免使用下划线并找到更好的命名约定。此示例中的命名也不是最佳做法。

const ShowMe = {
  data() {
    return {
      cTitle: null
    }
  },
  computed: {
    title: {
      set: function(val) {
        this.cTitle = val;
      },
      get: function() {
        return this.cTitle;
      }    
    }
  },
  template: `
    <div>
      should display title: {{title}} <br/>
      but instead typeof title: {{typeof title}}
    </div>`
};

const vm = new Vue({
  el: '#app',
  data: {
    aTitle: 'A Title'
  },
  components: {
    'show-me': ShowMe
  }
});

【讨论】:

    【解决方案4】:

    此代码将允许您初始化初始值,然后响应式更改 ShowMe 组件内的 dataTitle 字段。

    如果您想从外部组件更改属性,那么您应该不使用 dataTitle 字段并仅使用 props。

    const ShowMe = {
      props: {
        title: {
          type: String,
          default: ''
        }
      },
    
      data () {
        return {
          dataTitle: this.title
        }
      },
    
      template: `
        <div>
          should display title: {{dataTitle}} <br/>
          but instead typeof title: {{typeof dataTitle}}
        </div>`
    };
    

    您可能还需要能够在 ShowMe 内部和从外部组件更改属性。然后就可以使用下面的代码了:

    JS

    const ShowMe = {
      props: {
        title: {
          type: String,
          default: ''
        }
      },
    
      data () {
        return {
          dataTitle: this.title
        }
      },
    
      watch: {
        title (newValue, oldValue) {
           if (newValue !== oldValue) {
             this.dataTitle = newValue;
           }
        },
    
        dataTitle (newValue, oldValue) {
          if (newValue !== oldValue) {
            this.$emit('changeTitle', newValue);
          }
        }
      },
    
      template: `
        <div>
          should display title: {{dataTitle}} <br/>
          but instead typeof title: {{typeof dataTitle}}
        </div>`
    };
    
    const vm = new Vue({
      el: '#app',
      data: {
        aTitle: 'A Title'
      },
      components: {
        'show-me': ShowMe
      }
    });
    

    HTML

    <div id="app">
      <show-me :title="aTitle" @changeTitle="aTitle = $event"></show-me>
    </div>
    

    【讨论】:

      猜你喜欢
      • 2018-08-28
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2018-11-22
      • 2017-09-07
      • 2021-03-15
      • 1970-01-01
      相关资源
      最近更新 更多