在Vue中如何用数据来驱动用户界面

编辑推荐:诚征广告商金主入驻此广告位置,如有感兴趣的金主,欢迎邮件至:airenliao@gmail.com咨询相关合作事宜!!!(^_^)
特别声明,本文来源于@Evan Schultz的《Do it with Elegance: How to Create Data-Driven User Interfaces in Vue》。
虽然我们通常知道在应用程序中构建大多数视图(View)时需要哪些伟德1946手机版(Component),但很多时候我们并不知道这些伟德1946手机版在运行时是什么。这意味着我们需要基于应用程序状态、用户首选项或API的响应来构建一个页面。一个常见的情况是构建动态表单,其中需要整清楚的是:伟德1946手机版是由JSON对象配置的,还是基于用户的答案而更改的字段来构建 所有现代JavaScript框架(比如我们熟悉的Vue、React等)都有处理动态伟德1946手机版的方法。这篇文章将向您展示如何在Vue中实现它。JavaScript为上述场景提供了一个非常优雅和简单的解决方案。 一旦你看到使用Vue是这么的容易,你可能会受到启发,看到你从未考虑过的动态伟德1946手机版的应用程序! 在运行之前,我们需要先走一步,先介绍动态伟德1946手机版的基础知识,然后深入了解如何使用这些概念来构建你自己的动态表单构造器。

基础知识

Vue有一个内置伟德1946手机版,称为<component>。你可以在Vue指南中看到有关于动态伟德1946手机版的完整细节。 Vue指南是这样描述的:
你可以使用相同的挂载点,并使用保留元素动态地在多个伟德1946手机版之间切换,并动态绑定到它的属性。
这意味着在伟德1946手机版之间进行交换变得很简单: <component :is="componentType"> 让我们把它具体化一些,看看会发生什么。首先创建两个伟德1946手机版,分别名为DynamicOneDynamicTwo。这两个伟德1946手机版中的代码是相同的,只是name的值不一样: <template> <div>Dynamic Component One</div> </template> <script> export default { name: 'DynamicOne', } </script> 在我们的App.vue中实现快速切换这两个伟德1946手机版: import DynamicOne from './components/DynamicOne.vue' import DynamicTwo from './components/DynamicTwo.vue' export default { name: 'app', components: { DynamicOne, DynamicTwo }, data() { return { showWhich: 'DynamicOne' } } }
注意,data中的showWhich属性值是DynamicOne的字符串值,这是components对象中创建的name的值。
在我们的模板中,我们将设置两个按钮来切换两个动态伟德1946手机版: <button @click="showWhich = 'DynamicOne'">Show Component One</button> <button @click="showWhich = 'DynamicTwo'">Show Component Two</button> <component :is="showWhich"></component> 点击按钮将会用DynamicTwo替换DynamicOne
这个时候你可能会说,这又怎么样?是很方便,但也可以使用v-if来实现同样的效果。 当你意识到<component>和其他伟德1946手机版一样工作时,这个示例就开始发挥作用了,它可以与v-for这样的Vue指令结合起来使用,用于对迭代集合,或者使用:is可以绑定到一个inputdataprops或者是computed属性。

props和events

伟德1946手机版不是孤立存在的 —— 它们需要一种与周围世界交流的方式。如果使用Vue的话,那么这种交流是通过propsevents来完成的。 你可以在动态伟德1946手机版上指定与其他伟德1946手机版相同的属性和事件绑定,如果加载的伟德1946手机版不需要该属性,Vue将不会抱怨未知的"Attributes”或“properties”。 让我们修改伟德1946手机版显示的内容。DynamicOne伟德1946手机版只接受firstNamelastName,而另一个伟德1946手机版DynamicTwo接受firstNamelastNametitle 对于事件,我们将在DynamicOne中添加一个按钮,它将发出(emit)一个名为upperCase的事件;而在DynamicTwo中将发出一个名为lowerCase事件。 把它放在一起,动态伟德1946手机版看起来像这样: <component :is="showWhich" :firstName="person.firstName" :lastName="person.lastName" :title="person.title" @upperCase="switchCase('upperCase')" @lowerCase="switchCase('lowerCase')"> </component> 事实上并不是每个属性或事件都需要定义在我们正在切换的动态伟德1946手机版上。

先要了解props

此时,你可能会想,“如果伟德1946手机版是动态的,而不是每个伟德1946手机版都需要知道所有可能的props —— 需要知道props之前,并在模板中声明它们吗?” 值得庆幸的是,答案是否定的。Vue提供了一个快捷方式,可以使用v-bind将对象的所有键绑定到伟德1946手机版的props 这个时候模板可以简化为: <component :is="showWhich" v-bind="person" @upperCase="switchCase('upperCase')" @lowerCase="switchCase('lowerCase')"> </component>

表单形式

现在我们已经有了一个动态伟德1946手机版区块,接下来可以开始构建一个表单生成器。 让我们从一个基本的表单模式开始 —— 一个JSON对象,它描述了表单的字段、标签和选项等:
  • 文本和数字输入域
  • 一个下拉列表
开始的schema看起来像这样: schema: [ { fieldType: "SelectList", name: "title", multi: false, label: "Title", options: ["Ms", "Mr", "Mx", "Dr", "Madam", "Lord"] }, { fieldType: "TextInput", placeholder: "First Name", label: "First Name", name: "firstName" }, { fieldType: "TextInput", placeholder: "Last Name", label: "Last Name", name: "lastName" }, { fieldType: "NumberInput", placeholder: "Age", name: "age", label: "Age", minValue: 0 } ] 非常简单。在本例中,将保持这些简单的伟德1946手机版实现。 TextInput.vue: <template> <div> <label>{{ label }}</label> <input type="text" :name="name" :placeholder="placeholder" /> </div> </template> <script> export default { name: 'TextInput', props: ['placeholder', 'lable', 'name'] } </script> SelectList.vue <template> <div> <label>{{ label }}</label> <select :multiple="nulti"> <option v-for="option in options" :key="option">{{ option }}</option> </select> </div> </template> <script> export default { name:'SelectList', props: ['multi', 'options', 'name', 'label'] } </script> 基于这个schema要生成表单,还要加加下面的内容: <component v-for="(field, index) in schema" :key="index" :is="field.fieldType" v-bind="field"> </component> 结果如下:

数据绑定

如果表单生成但不绑定数据,估计也没啥有用。上面生成了一个表单,但没有绑定数据。你可以第一反应就是在伟德1946手机版中使用v-model来绑定schema中的value属性。 <input type="text" :name="name" v-model="value" :placeholder="placeholder"> 这种方法有一些潜在的缺陷,但是Vue会给我们反馈相应的错误或警告信息: 虽然Vue确实给伟德1946手机版提供双向数据绑定,但框架仍然倾向于单向数据流。我们试图在伟德1946手机版中直接改变父类的数据,所以Vue会警告我们,如上图所示。 仔细看看v-model,其实他没有那么多的魔力,所以让我们按照Vue指南中关于表单输入伟德1946手机版的描述来分解它。 <input v-model="something"> 它等同于: <input v-bind:value="something" v-on:input="something = $event.target.value"> 我们想要完成的是:
  • 让父元素为子伟德1946手机版提供值
  • 让父节点知道一个值已被更新
通过绑定到:value并发出一个@input事件来通知父元素,进程发生了一些变化。 根据这个描述对TextInput伟德1946手机版进行修改: <div> <label>{{label}}</label> <input type="text" :name="name" :value="value" @input="$emit('input',$event.target.value)" :placeholder="placeholder"> </div> 由于父类负责提供值,所以它也负责处理绑定到它自己的伟德1946手机版状态。为此,我们可以在<component>签上使用v-model FormGenerator.vue: <component v-for="(field, index) in schema" :key="index" :is="field.fieldType" v-model="formData[field.name]" v-bind="field"> </component> 注意,我们如何使用v-model="formDtata[field.name]"。我们需要在数据属性上提供一个对象: export default { data() { return { formData: { firstName: 'Evan' }, } } } 我们可以让对象为空,或者如果我们有一些我们想要设置的初始字段,就可以在这里指定它们。 现在我们已经完成了生成表单的过程,这个伟德1946手机版承担了相当多的责任。虽然代码不是很复杂,但是表单生成器自身要是可复用的伟德1946手机版,那就更好了。

让生成器可重用

对于这个表单生成器,我们希望将schema传递给prop,并能够在伟德1946手机版之间设置数据绑定。 当使用生成器时,模板GeneratorDemo.vue变为: <form-generator :schema="schema" v-model="formData"></form-generator> 这对父伟德1946手机版进行了相当大的清理。它只关心FormGenerator,并不关心可以使用的每个输入类型、连接事件等。 接下来,创建一个名为FormGenerator的伟德1946手机版。这将最初可复制的代码变得并不重要,重要的是做了一些关键的调整:
  • v-model改变:value@input事件处理
  • props中添加valueschema
  • 实现updateForm
FormGenerator伟德1946手机版变成这样: <component v-for="(field, index) in schema" :key="index" :is="field.fieldType" :value="formData[field.name]" @input="updateForm(field.name, $event)" v-bind="field"> </component> import NumberInput from '@/components/v5/NumberInput' import SelectList from '@/components/v5/SelectList' import TextInput from '@/components/v5/TextInput' export default { name: "FormGenerator", components: { NumberInput, SelectList, TextInput }, props: ['schema', 'value'], data() { return { formData: this.value || {} }; }, methods: { updateForm(fieldName, value) { this.$set(this.formData, fieldName, value); this.$emit('input', this.formData) } } }; 由于formData属性并不知道我们可以传入所有可能的字段,所以希望使用this.$set让Vue可以跟踪任何变化,并允许FormGenerator伟德1946手机版跟踪它自己的内部状态。 现在我们有了一个基本的可重用的表单生成器。可以在一个伟德1946手机版内使用它: GeneratorDemo.vue: <form-generator :schema="schema" v-model="formData"></form-generator> import FormGenerator from '@/components/v5/FormGenerator' export default { name: "GeneratorDemo", components: { FormGenerator }, data() { return { formData: { firstName: 'Evan' }, schema: [{ /* .... */ }, } } }
现在,你已经了解了表单生成器。通过这个简单的示例学习了如何利用Vue的动态伟德1946手机版的基础来创建一些高度动态,数据驱动的UI。文章中整个示例的代码可以在GitHub上获取到,或者在CodeSandbox上进行修改。如果你有任何问题或想要聊的地方,可以通过TwitterGitHub电子邮件联系我。你也可以在下面的评论中与我们一起探讨相关的话题。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等伟德19463331脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。
如需转载,烦请注明出处:https://www.w3cplus.com/vue/how-to-create-data-driven-user-interfaces-in-vue.html
返回顶部