【问题标题】:Validating object structure in vue.js在 vue.js 中验证对象结构
【发布时间】:2017-12-17 07:31:02
【问题描述】:

我目前正在 vue.js 中构建一个组件,但遇到了一点问题。你看,你可以给我的组件提供很多参数,所以为了清楚起见,我决定采用以下方法:

<script type="text/javascript">
    Vue.$noClientConf = {
    'cmp_name':         'NoClient', 
    'cmp_title':        'Selection du client',
    'url':              'ajax/getclients.php',
    'parent':           null,
    'opt_texte':        'NomClientFR',
    'opt_valeur':       'NoClient',
    'cmp_max_options':  3,
    'opt_custom':       null,
    'data_size':        10,
    'data_style':       'btn btn-default btn-sm',
    'data_live_search': 'true'
    };
</script>

<div id="app">

  <div class="col-lg-2">
    <flex-select ref="NoClient" :conf="Vue.$noClientConf"></flex-select>
  </div>

</div>

<script type="text/javascript">
    var app = new Vue({
      el: "#app",
      data:{Vue}
    });
</script>

基本上,我定义了一个包含必要参数的对象并将其提供给我的组件。问题是我想为其中一些参数定义一些默认值,这样用户就不必全部列出。

现在,我阅读了有关 Vue.js 道具验证的内容,发现它非常适合我想做的事情。但是,虽然您可以验证道具是否是对象,但您似乎无法验证对象的结构。例如,我希望能够做到:

props: {
        config.cmp_name: {
            type:String,
            required: true
        },
        config.cmp_title:{
            type:String,
            required: true
        }
    }

所以我的问题基本上是......有没有办法做到以上几点?

【问题讨论】:

    标签: javascript validation vue.js


    【解决方案1】:

    如果您想使用custom validator,最佳做法是使用Set() object

    例子:

    ExampleComponent 组件需要的对象输入:

    const obj = {
        block1: {
          icon: 'example',
          title: 'example',
          content: 'example'
        },
        block2: {
          icon: 'example',
          title: 'example',
          content: 'example'
        }
      };
    

    带有自定义验证器的组件:

    export default {
        name: 'ExampleComponent',
        props: {
          data: {
            type: Object,
            validator: (o) => {
              const set = new Set();
              set.add(!!(o.block1 && o.block1.icon && typeof o.block1.icon === 'string'));
              set.add(!!(o.block1 && o.block1.title && typeof o.block1.title === 'string'));
              set.add(!!(o.block1 && o.block1.content && typeof o.block1.content === 'string'));
              set.add(!!(o.block2 && o.block2.icon && typeof o.block2.icon === 'string'));
              set.add(!!(o.block2 && o.block2.title && typeof o.block2.title === 'string'));
              set.add(!!(o.block2 && o.block2.content && typeof o.block2.content === 'string'));
              return !set.has(false);
            },
          },
          color: {
            type: String,
            validator: value => ['black', 'white'].includes(value),
          },
        },
      };
    
    

    【讨论】:

      【解决方案2】:

      使用object binding syntax

      <flex-select ref="NoClient" v-bind="defaults"></flex-select>
      

      这将传递 所有 defaults 的属性,并验证您需要的属性。

      props: {
        cmp_name: {
          type:String,
          required: true
        },
        cmp_title:{
          type:String,
          required: true
        }
      }
      

      否则,您可以将函数用作custom validator

      props:{
        conf: {
          validator(config){
            let cmp_name = config.cmp_name && typeof config.cmp_name === "string"
            let cmp_title = config.cmp_title && typeof config.cmp_title === "string"
            return cmp_name && cmp_title
          }
        }
      }
      

      FWIW,我无法让 Vue.$noClientConf 在示例中工作。相反,我只是创建了一个默认对象。

      console.clear()
      
      const defaults = {
        'cmp_name':         'NoClient', 
        'cmp_title':        'Selection du client',
        'url':              'ajax/getclients.php',
        'parent':           null,
        'opt_texte':        'NomClientFR',
        'opt_valeur':       'NoClient',
        'cmp_max_options':  3,
        'opt_custom':       null,
        'data_size':        10,
        'data_style':       'btn btn-default btn-sm',
        'data_live_search': 'true'
      };
      
      Vue.component("flex-select",{
        props: {
        cmp_name: {
          type:String,
          required: true
        },
        cmp_title:{
          type:String,
          required: true
        }
      },
        template:`
          <div>{{cmp_name}} {{cmp_title}}</div>
        `
      })
      
      new Vue({
        el:"#app",
        data:{
          defaults
        }
      })
      <script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
      <div id="app">
        <flex-select v-bind="defaults"></flex-select>
        {{defaults}}
      </div>

      【讨论】:

      • 未缩小版本的 Vue 无法通过名称了解自身,因此您可能需要查看此帖子 here 以获取解决方案。除此之外,您的解决方案完美运行。谢谢:)
      猜你喜欢
      • 2018-06-23
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 2018-12-04
      • 2021-04-12
      • 1970-01-01
      • 2011-01-02
      • 2020-09-03
      相关资源
      最近更新 更多