【问题标题】:Access props value in another props' validator在另一个 props 的验证器中访问 props 值
【发布时间】:2019-11-16 03:54:36
【问题描述】:

我想在另一个 props 的验证器中访问一个 props 值:

props: {
  type: {
    type: String,
    default: "standard"
  },
  size: {
    type: String,
    default: "normal",
    validator(value) {
      // below I want to access the props `type` from above.
      return (this.type !== "caution" || this.type !== "primary") && value !== "mega"
    }
  }
}

但我收到了TypeError: Cannot read property 'type' of undefined。 有什么想法吗?

【问题讨论】:

    标签: vue.js vuejs2 vue-component


    【解决方案1】:

    prop 的 validator 中的 this 变量没有引用 Vue 实例。而且,不幸的是,没有真正的方法可以在 prop 的 validator 函数中引用另一个 prop 的值。


    您可以做的一件事是在 Vue 实例的 $props 对象上设置一个观察者,将 immediate 选项设置为 true 以便在创建组件时触发观察者。该观察者可以触发验证逻辑,其中this 是对 Vue 实例的引用。

    这是一个简单的例子:

    Vue.config.productionTip = false;
    Vue.config.devtools = false;
    
    Vue.component('child', {
      template: '<div></div>',
      props: {
        type: {
          type: String,
          default: "standard"
        },
        size: {
          type: String,
          default: "normal"
        }
      },
      methods: {
        validateProps() {
          if ((this.type === "caution" || this.type === "primary") && this.size === "mega") {
            console.error('Invalid props');
          }
        }
      },
      watch: {
        $props: {
          immediate: true,
          handler() {
            this.validateProps();
          }
        }
      }
    });
    
    new Vue({
      el: '#app'
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
      <child type="caution" size="mega"></child>
    </div>

    另一种选择是将具有typesize 属性的对象作为单个道具传递。这样,该道具的validator 将引用这两个值。

    Vue.config.productionTip = false;
    Vue.config.devtools = false;
    
    Vue.component('child', {
      template: '<div></div>',
      props: {
        config: {
          type: Object,
          default: () => ({ type: "standard", size: "normal" }),
          validator({ type, size }) {
            return !((type === "caution" || type === "primary") && size === "mega");
          }
        }
      }
    });
    
    new Vue({
      el: '#app'
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
      <child :config="{ type: 'caution', size: 'mega'}"></child>
    </div>

    (请注意:您的验证逻辑可能不正确。正如它所写的那样,括号中的语句将始终评估为true。我在示例中更新了该逻辑,使其符合我的意思。)

    【讨论】:

    • 嘿伙计,谢谢您的建议,我选择选项 2。它简单且有意义。很想知道为什么您解释的访问道具不可用。谢谢
    • 谢谢您的纠正。为什么我不能直接将对象设置为default?为什么我必须从函数中返回它。
    • 在 javascript 中,对象是通过引用设置的,所以如果默认值只是一个对象,那么使用默认值的组件的每个实例都将指向同一个对象。通过使其成为返回对象的函数,将为每个使用默认值的组件实例创建一个新对象。
    • @thanksd 你确定吗? let a = {b: 1} 然后 () =&gt; a 这将返回 a 包含指向 b 的指针。实际上,如果返回一个对象会创建一个具有一组新引用的新对象,那将是非常糟糕的!?
    • @Estradiaz,我不确定你的意思。这是一个小提琴示例,可能有助于理解对象引用的工作原理:jsfiddle.net/75j9xuvy
    【解决方案2】:

    如果您只需要验证一次,只需在mounted() 处理程序中进行。这未通过我们的笑话测试,并在浏览器中记录错误。

    props: {
      type: {
        type: String,
        default: "standard"
      },
      size: {
        type: String,
        default: "normal"
      }
    },
    mounted() {
      if ((this.type === "caution" || this.type === "primary") && this.size === "mega") {
        console.error('Invalid props');
      }
    }
    

    【讨论】:

      【解决方案3】:

      这是不可能的。 VUE项目中的提案很少,但都被拒绝了:

      https://github.com/vuejs/vue/issues/3495

      https://github.com/vuejs/vue/issues/6787

      https://github.com/vuejs/vue/issues/9925

      这种情况的简单方法是使用计算属性或验证created 钩子上的属性。在这种情况下,所有属性都可用。

      【讨论】:

        猜你喜欢
        • 2019-01-10
        • 2019-03-30
        • 1970-01-01
        • 2018-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-13
        相关资源
        最近更新 更多