为什么回到上一步没有显示v-show?
Why doesn't v-show displayed when I go back to the previous step?
我在 VUE 中有一个 SAP,它包含一个包含 4 个步骤的表单。
当在第一步按钮中提交并重定向到第二步时,如果我 return 到第一步,最后一个组件将停止显示,尽管在更改组件之前已显示。
这是我的模板
<input
type="text"
id="animalName"
ref="animalName"
v-model="animalFormInfo.name"
@keypress="onChangeName($event)"
@keyup="onChangeName($event)"
/>
<div class="loader-spinner" v-if="loading">
<app-loader>
</div>
</div>
</div>
</div>
<div v-show="isNameCompleted">
<div class="from-group">
<h1 class="title">
For
<span>{{this.formInfo.name}}</span>, you have:
</h1>
<div class="list-services">
<div
class="column-service"
v-for="estimation in filteredEstimation"
v-bind:key="estimation.name"
>
<div>{{estimation.name}}</div>
<div>{{estimation.description}}</div>
<div>{{estimation.price.toString().replace(".", ",")}}</div>
</div>
</div>
</div>
</div>
<div class="button-line" v-show="isLoaderFinished"></div>
<div class="forward" v-show="isLoaderFinished">
<div class="forward-button">
<button
ref="submit"
v-bind:disabled="!isFormCompleted"
type="submit"
@click="navigateToCreate"
>
SEND INFO
</button>
</div>
</div>
下面是我控制组件负载的数据和方法
data() {
return {
step: 1,
isFormCompleted: false,
isBreedSelected: false,
isNameCompleted: false,
loading: false,
isLoaderFinished: false,
myTimeout: 0
};
},
methods:{
onChangeName(event) {
if (this.myTimeout >= 0 && event) {
clearTimeout(this.myTimeout);
this.loading = true;
this.isNameCompleted = false;
}
this.myTimeout = window.setTimeout(() => {
this.isNameCompleted = true;
const typedAnimalName = event.target._value;
this.capitalizeAnimalName(typedAnimalName);
this.loading = false;
this.isLoaderFinished = true;
this.isFormCompleted = true;
setTimeout(() => (this.$refs.scrolled_3.focus()), 10);
}, 2200);
},
capitalizeAnimalName(typedAnimalName) {
var splitAnimalName = typedAnimalName.toLowerCase().split(' ');
for (var i = 0; i < splitAnimalName.length; i++) {
splitAnimalName[i] = splitAnimalName[i].charAt(0).toUpperCase() + splitAnimalName[i].substring(1);
}
return this.animalName = splitAnimalName.join(' ');
},
},
一旦我到达第 2 步,return 进入第 1 步,只有输入 ID 为“animalName”的信息才会显示。
我究竟做错了什么?
为什么加载第一个组件时它遵循逻辑并显示它们并且一旦我转到下一个它们就消失了?
感谢大家的宝贵时间和提前帮助
是因为当你回到第一页时组件是re-rendering,所以所有的默认状态都会生效。尝试使用 Vuex 保存您的状态,以便所有组件都将由商店中的状态控制。
如果每个步骤都是自己的组件,您可以使用keep-alive
组件来缓存组件及其状态,这样当您在它们之间切换时,它们的状态会被保留。在这种情况下,我个人更喜欢使用 Vuex,因为它更简单。
<keep-alive>
<step-1-component v-if="step === 1"></step-1-component>
<step-2-component v-if="step === 2"></step-2-component>
<step-3-component v-if="step === 3"></step-3-component>
</keep-alive>
问题是组件的状态不是持久化的。
对此有多种解决方案。
1。使用 Vuex
全局管理状态
这可能是处理此类情况的默认或最常用方式。您无需将数据存储在组件中,而是使用该库来管理状态。很可能你可以在你的项目中实现 vuex 而不是继续阅读。这是一个可靠的选择,有太多优点无法一一列举。
2。在父组件中封装表单状态。
您可以在父对象内为相关数据创建状态,而不是在步骤组件内管理状态。
示例:
<Step2
v-if="step === 2"
:formData="formData"
:updateFormData="updateFormData"
:nextStep="() => gotoStep(3)"
></Step2>
想法是 Step2
组件将通过 formData
属性传递数据。每当数据发生变化时,都会用新数据调用 updateFormData
函数。您甚至可以使用 v-model
.
来简化它
3。 DIY商店
如果您使用的是 Vue js 2(>= 2.6,< 3),您可以使用 observable
Vue 2.6+
创建一个 store.js
文件
import Vue from "vue";
export const store = Vue.observable({
step: 1,
isFormCompleted: false,
isBreedSelected: false,
isNameCompleted: false,
loading: false,
isLoaderFinished: false,
});
然后你可以从任何组件调用你的store.js
,如果你在beforeCreate
钩子中将它分配给this
,你可以像使用数据一样使用它(this.store.isFormCompleted
在脚本中,store.isFormCompleted
在模板中)
import { store} from 'store.js';
//...
beforeCreate(){
this.store = store;
}
如果你想跳过额外的 store.
,你甚至可以解构存储对象。
Vue 3
与那里的另一个类似,但使用一个 reactive()
(或多个 ref()
)。如果您想让我对此进行扩展,请告诉我。
我在 VUE 中有一个 SAP,它包含一个包含 4 个步骤的表单。 当在第一步按钮中提交并重定向到第二步时,如果我 return 到第一步,最后一个组件将停止显示,尽管在更改组件之前已显示。 这是我的模板
<input
type="text"
id="animalName"
ref="animalName"
v-model="animalFormInfo.name"
@keypress="onChangeName($event)"
@keyup="onChangeName($event)"
/>
<div class="loader-spinner" v-if="loading">
<app-loader>
</div>
</div>
</div>
</div>
<div v-show="isNameCompleted">
<div class="from-group">
<h1 class="title">
For
<span>{{this.formInfo.name}}</span>, you have:
</h1>
<div class="list-services">
<div
class="column-service"
v-for="estimation in filteredEstimation"
v-bind:key="estimation.name"
>
<div>{{estimation.name}}</div>
<div>{{estimation.description}}</div>
<div>{{estimation.price.toString().replace(".", ",")}}</div>
</div>
</div>
</div>
</div>
<div class="button-line" v-show="isLoaderFinished"></div>
<div class="forward" v-show="isLoaderFinished">
<div class="forward-button">
<button
ref="submit"
v-bind:disabled="!isFormCompleted"
type="submit"
@click="navigateToCreate"
>
SEND INFO
</button>
</div>
</div>
下面是我控制组件负载的数据和方法
data() {
return {
step: 1,
isFormCompleted: false,
isBreedSelected: false,
isNameCompleted: false,
loading: false,
isLoaderFinished: false,
myTimeout: 0
};
},
methods:{
onChangeName(event) {
if (this.myTimeout >= 0 && event) {
clearTimeout(this.myTimeout);
this.loading = true;
this.isNameCompleted = false;
}
this.myTimeout = window.setTimeout(() => {
this.isNameCompleted = true;
const typedAnimalName = event.target._value;
this.capitalizeAnimalName(typedAnimalName);
this.loading = false;
this.isLoaderFinished = true;
this.isFormCompleted = true;
setTimeout(() => (this.$refs.scrolled_3.focus()), 10);
}, 2200);
},
capitalizeAnimalName(typedAnimalName) {
var splitAnimalName = typedAnimalName.toLowerCase().split(' ');
for (var i = 0; i < splitAnimalName.length; i++) {
splitAnimalName[i] = splitAnimalName[i].charAt(0).toUpperCase() + splitAnimalName[i].substring(1);
}
return this.animalName = splitAnimalName.join(' ');
},
},
一旦我到达第 2 步,return 进入第 1 步,只有输入 ID 为“animalName”的信息才会显示。 我究竟做错了什么? 为什么加载第一个组件时它遵循逻辑并显示它们并且一旦我转到下一个它们就消失了?
感谢大家的宝贵时间和提前帮助
是因为当你回到第一页时组件是re-rendering,所以所有的默认状态都会生效。尝试使用 Vuex 保存您的状态,以便所有组件都将由商店中的状态控制。
如果每个步骤都是自己的组件,您可以使用keep-alive
组件来缓存组件及其状态,这样当您在它们之间切换时,它们的状态会被保留。在这种情况下,我个人更喜欢使用 Vuex,因为它更简单。
<keep-alive>
<step-1-component v-if="step === 1"></step-1-component>
<step-2-component v-if="step === 2"></step-2-component>
<step-3-component v-if="step === 3"></step-3-component>
</keep-alive>
问题是组件的状态不是持久化的。
对此有多种解决方案。
1。使用 Vuex
全局管理状态
这可能是处理此类情况的默认或最常用方式。您无需将数据存储在组件中,而是使用该库来管理状态。很可能你可以在你的项目中实现 vuex 而不是继续阅读。这是一个可靠的选择,有太多优点无法一一列举。
2。在父组件中封装表单状态。
您可以在父对象内为相关数据创建状态,而不是在步骤组件内管理状态。
示例:
<Step2
v-if="step === 2"
:formData="formData"
:updateFormData="updateFormData"
:nextStep="() => gotoStep(3)"
></Step2>
想法是 Step2
组件将通过 formData
属性传递数据。每当数据发生变化时,都会用新数据调用 updateFormData
函数。您甚至可以使用 v-model
.
3。 DIY商店
如果您使用的是 Vue js 2(>= 2.6,< 3),您可以使用 observable
Vue 2.6+
创建一个 store.js
文件
import Vue from "vue";
export const store = Vue.observable({
step: 1,
isFormCompleted: false,
isBreedSelected: false,
isNameCompleted: false,
loading: false,
isLoaderFinished: false,
});
然后你可以从任何组件调用你的store.js
,如果你在beforeCreate
钩子中将它分配给this
,你可以像使用数据一样使用它(this.store.isFormCompleted
在脚本中,store.isFormCompleted
在模板中)
import { store} from 'store.js';
//...
beforeCreate(){
this.store = store;
}
如果你想跳过额外的 store.
,你甚至可以解构存储对象。
Vue 3
与那里的另一个类似,但使用一个 reactive()
(或多个 ref()
)。如果您想让我对此进行扩展,请告诉我。