鬼牌,在此借用的意思是「可以成为任何一张牌」
Dynamic Components 技术使用 <component :is="">
让 component 可以抽换成其它已经规画好的 component。
不管是申请信用卡、成为购物网站会员、基金申购平台帐号,可能就有机会填写到这麽长的表单,设计师为了让使用者的体验较好,所以会把长型表单改成多个短表单,一步一步的引导使用者将表单填写完毕。
在这个过程,如果需要将资料暂存在 localStorage 中,就变成是一件麻烦的事情,是否要一段一段的将资料储存在各别的 localStorage 中?还是有其它的办法呢?
以下图为例,拿四个栏位的表单当作长型表单。(数量请大家自行指数成长)
通常都是分成第一步、第二步....这样。
原本,如果是很长的表单,我们会这样写。对工程师来说方便,data 也只有一个要储存在 localStorage 也只有一个栏位就好。
App.vue
<template>
<div id="app">
<form @submit.prevent="onSubmit">
<div>
<label for="field1">
field1
<input type="text" id="field1"
v-model="data.field1">
</label>
</div>
<div>
<label for="field2">
field2
<input type="text" id="field2"
v-model="data.field2">
</label>
</div>
<div>
<label for="field3">
field3
<input type="text" id="field3"
v-model="data.field3">
</label>
</div>
<div>
<label for="field4">
field4
<input type="text" id="field4"
v-model="data.field4">
</label>
</div>
<input type="submit">
</form>
</div>
</template>
export default {
name: 'App',
methods: {
onSubmit() {
console.log('submit', JSON.stringify(this.mock));
},
},
data() {
return {
index: 1,
mock: {
field1: 'field_data1',
field2: 'field_data2',
field3: 'field_data3',
field4: 'field_data4',
},
};
},
};
直接把表单拆成两个 component。
并且将栏位拆进 component 里面 (因为接下来要抽换它们)
<template>
<div id="app">
<form @submit.prevent="onSubmit">
<step1
:data="mock"
@update:data="mock=$event"
></step1>
<step2
:data="mock"
@update:data="mock=$event"
></step2>
<input type="submit">
</form>
</div>
</template>
注册 2 个 component
import step1 from '@/components/LongForm/step1.vue';
import step2 from '@/components/LongForm/step2.vue';
export default {
name: 'App',
// ...
components: {
step1,
step2,
},
// ...
}
step1.vue
因为两步目前长得一样,所以只看其中一个就好了
<template>
<div>
<div>
<label for="field1">
field1
<input type="text"
id="field1"
:value="data.field1"
@input="$emit('update:data', {
...data,
field1: $event.target.value
})">
</label>
</div>
<div>
<label for="field2">
field2
<input type="text"
id="field2"
:value="data.field2"
@input="$emit('update:data', {
...data,
field2: $event.target.value
})">
</label>
</div>
</div>
</template>
在此,我们已经把 v-model 拆开写,「单纯只有栏位 binding 的 code 」只会出现在 html 上面。
在此只是一个简单的 pure component 如果要加上复杂的逻辑,就有相当乾净的环境可以加上去。
export default {
name: 'LongForm1',
props: {
data: {
type: Object,
requried: true,
},
}
};
<component :is="">
并且将 :is
binding 成 step1 和 setp2 的 component 名字。
<template>
<div id="app">
<form @submit.prevent="onSubmit">
<component
:is="'step1'"
:data="mock"
@update:data="mock=$event"
></component>
<component
:is="'step2'"
:data="mock"
@update:data="mock=$event"
></component>
<input type="submit">
</form>
</div>
</template>
<component :is="">
换成同一个 <component :is="">
时,可以注意两个 component 的 v-bind 和 v-on 必须要一样。
<template>
<div id="app">
<div>现在是第 {{ current_step }} 步</div>
<form @submit.prevent="onSubmit">
<component
:is="`step${index}`"
:data="mock"
@update:data="mock=$event"
></component>
<input v-if="current_step === 2" type="submit">
<input v-else type="button" value="下一步" @click="onNext">
</form>
</div>
</template>
export default {
name: 'App',
// ...
data() {
return {
current_step: 1,
// ...
}
},
methods: {
onNext() {
this.current_step += 1;
console.log('current_step', this.current_step);
},
onSubmit() {
console.log('submit', JSON.stringify(this.mock));
},
},
},
一开始是这样
第一步
第二步
写到第二步,如果重新整理,会回到第一步。
最後提交表单。
在 onNext 的时候,就可以储存起来。
而且,因为是长表单,所以当下到第几步和资料都给它储存下来。
修改的程序
在 created 要把 localStorage 读取出来恢复资料。
在 onNext 的地方要在 localStorage 储存现况。
export default {
name: 'App',
// ...
created() {
const demoStatus = JSON.parse(localStorage.getItem('DemoMock'));
if (demoStatus.data) {
this.mock = demoStatus.data;
}
},
// ...
methods: {
onNext() {
this.current_step += 1;
console.log('current_step', this.current_step);
localStorage.setItem('DemoMock', JSON.stringify({
setp: this.current_step,
data: this.mock
}));
},
}
}
基本上目前看到的方法大致上都如下图所示,所以我目前实作的也是如此, 因为脑子里没有更好的解决方案(在...
从基本的 HTML、CSS 网页设计开始入门,先学习静态版面设计技巧,再带入动态的 JavaScri...
前一天我们介绍了用来资料处理最基本的pandas套件 那今天我们则是来谈一下不同的档案类型 我们都知...
Definition of a Semigroup 一个集合(Set)或称型别(Type) 有 co...
一. 前言 在如今社群网路蓬勃的时代,从网路充斥着许多文字资料,要如何有效的分析文字让电脑可以知道我...