在Vue中如何用数据来驱动用户界面——动态页面 侵立删

虽然我们通常知道在应用程序中构建大多数视图(View)时需要哪些组件(Component),但很多时候我们并不知道这些组件在运行时是什么。这意味着我们需要基于应用程序状态、用户首选项或API的响应来构建一个页面。一个常见的情况是构建动态表单,其中需要整清楚的是:组件是由JSON对象配置的,还是基于用户的答案而更改的字段来构建

所有现代JavaScript框架(比如我们熟悉的Vue、React等)都有处理动态组件的方法。这篇文章将向您展示如何在Vue中实现它。JavaScript为上述场景提供了一个非常优雅和简单的解决方案。

一旦你看到使用Vue是这么的容易,你可能会受到启发,看到你从未考虑过的动态组件的应用程序!

在运行之前,我们需要先走一步,先介绍动态组件的基础知识,然后深入了解如何使用这些概念来构建你自己的动态表单构造器。

基础知识

Vue有一个内置组件,称为<component>。你可以在Vue指南中看到有关于动态组件的完整细节。

Vue指南是这样描述的:

你可以使用相同的挂载点,并使用保留元素动态地在多个组件之间切换,并动态绑定到它的属性。

这意味着在组件之间进行交换变得很简单:

<component :is="componentType">  

让我们把它具体化一些,看看会发生什么。首先创建两个组件,分别名为DynamicOneDynamicTwo。这两个组件中的代码是相同的,只是name的值不一样:

<template>  
    <div>Dynamic Component One</div>
</template>  

<script>  
    export default {  
        name: 'DynamicOne',
    }
</script>  

在我们的App.vue中实现快速切换这两个组件:

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的值。

在我们的模板中,我们将设置两个按钮来切换两个动态组件:

<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>和其他组件一样工作时,这个示例就开始发挥作用了,它可以与v-for这样的Vue指令结合起来使用,用于对迭代集合,或者使用:is可以绑定到一个inputdataprops或者是computed属性。

props和events

组件不是孤立存在的 —— 它们需要一种与周围世界交流的方式。如果使用Vue的话,那么这种交流是通过propsevents来完成的。

你可以在动态组件上指定与其他组件相同的属性和事件绑定,如果加载的组件不需要该属性,Vue将不会抱怨未知的"Attributes”或“properties”。

让我们修改组件显示的内容。DynamicOne组件只接受firstNamelastName,而另一个组件DynamicTwo接受firstNamelastNametitle

对于事件,我们将在DynamicOne中添加一个按钮,它将发出(emit)一个名为upperCase的事件;而在DynamicTwo中将发出一个名为lowerCase事件。

把它放在一起,动态组件看起来像这样:

<component  
    :is="showWhich" 
    :firstName="person.firstName"
    :lastName="person.lastName"
    :title="person.title"
    @upperCase="switchCase('upperCase')"
    @lowerCase="switchCase('lowerCase')">
</component>  

事实上并不是每个属性或事件都需要定义在我们正在切换的动态组件上。

先要了解props

此时,你可能会想,“如果组件是动态的,而不是每个组件都需要知道所有可能的props —— 需要知道props之前,并在模板中声明它们吗?”

值得庆幸的是,答案是否定的。Vue提供了一个快捷方式,可以使用v-bind将对象的所有键绑定到组件的props

这个时候模板可以简化为:

<component  
    :is="showWhich" 
    v-bind="person"
    @upperCase="switchCase('upperCase')"
    @lowerCase="switchCase('lowerCase')">
</component>  

 

表单形式

现在我们已经有了一个动态组件区块,接下来可以开始构建一个表单生成器。

让我们从一个基本的表单模式开始 —— 一个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
    }
]

非常简单。在本例中,将保持这些简单的组件实现。

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>  

结果如下:

 

数据绑定

如果表单生成但不绑定数据,估计也没啥有用。上面生成了一个表单,但没有绑定数据。你可以第一反应就是在组件中使用v-model来绑定schema中的value属性。

<input 
    type="text"  
    :name="name"
    v-model="value"
    :placeholder="placeholder">

这种方法有一些潜在的缺陷,但是Vue会给我们反馈相应的错误或警告信息:

虽然Vue确实给组件提供双向数据绑定,但框架仍然倾向于单向数据流。我们试图在组件中直接改变父类的数据,所以Vue会警告我们,如上图所示。

仔细看看v-model,其实他没有那么多的魔力,所以让我们按照Vue指南中关于表单输入组件的描述来分解它。

<input v-model="something"> 

它等同于:

<input  
    v-bind:value="something"
    v-on:input="something = $event.target.value">

我们想要完成的是:

  • 让父元素为子组件提供值
  • 让父节点知道一个值已被更新

通过绑定到:value并发出一个@input事件来通知父元素,进程发生了一些变化。

根据这个描述对TextInput组件进行修改:

<div>
    <label>{{label}}</label>
    <input 
        type="text"
        :name="name"
        :value="value"
        @input="$emit('input',$event.target.value)"
        :placeholder="placeholder">
</div>

由于父类负责提供值,所以它也负责处理绑定到它自己的组件状态。为此,我们可以在<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'
            },
        }
    }
}

我们可以让对象为空,或者如果我们有一些我们想要设置的初始字段,就可以在这里指定它们。

现在我们已经完成了生成表单的过程,这个组件承担了相当多的责任。虽然代码不是很复杂,但是表单生成器自身要是可复用的组件,那就更好了。


原文: https://www.w3cplus.com/vue/how-to-create-data-driven-user-interfaces-in-vue.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值