我对vue-router
有一个奇怪的问题。
我为用户提供了一个简单的CRUD应用程序。
它包含四个不同的视图:
如果我是第一次进入ID为1的用户的编辑页面,则一切都像一个超级按钮。 但是,如果我返回并单击另一个用户并转到编辑页面,它将显示带有ID为1的用户值的表单,并且没有新的Ajax请求。
似乎该组件将被重用。
我试图给表单子组件不同的:key
值,但没有成功。
<router-view :key="$route.fullPath"></router-view>
在路由器视图上设置密钥也没有成功...
如果我重新加载浏览器,它将正确显示
以下是一个示例:
我的路线:
import Index from "./views/Index";
import Show from "./views/Show";
import Edit from "./views/Edit";
import Create from "./views/Create";
export default [
{
path: '/admin/users',
name: 'users.index',
component: Index
},
{
path: '/admin/users/create',
name: 'users.create',
component: Create
},
{
path: '/admin/users/:id',
name: 'users.show',
component: Show,
props: true
},
{
path: '/admin/users/:id/edit',
name: 'users.edit',
component: Edit,
props: true
},
];
编辑组件(创建是不带id的sme):
<template>
<ResourceForm
resource="user"
:resource-id="id"
@cancel="$router.push({name: 'users.index'})"
/>
</template>
<script>
import ResourceForm from "../../../components/ResourceForm";
export default {
components: {ResourceForm},
props: ['id'],
}
</script>
ResourceForm组件:
<template>
<form @submit.prevent="submitResourceForm">
<component
v-for="(field, index) in fields"
:key="field.name + index"
:ref="`${field.name}-field`"
:is="field.component"
:field="field"
:validation-errors="getValidationErrors(field)"
/>
<div class="mt-8 border-t border-gray-200 pt-5">
<div class="flex justify-end">
<span class="inline-flex rounded-md shadow-sm">
<button type="button" @click="$emit('cancel')"
class="py-2 px-4 border border-gray-300 rounded-md text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition duration-150 ease-in-out">
{{this.cancelText}}
</button>
</span>
<span class="ml-3 inline-flex rounded-md shadow-sm">
<button type="submit"
class="btn">
{{this.submitText}}
</button>
</span>
</div>
</div>
</form>
</template>
<script>
import _ from 'lodash';
import api from "../lib/api";
import Form from "../lib/mixins/Form";
export default {
mixins: [Form],
props: {
resource: {
type: String,
required: true
},
resourceId: {
required: false,
default: null
},
cancelText: {
type: String,
default: 'Cancel'
},
submitText: {
type: String,
default: 'Submit'
},
},
data() {
return {
fields: []
}
},
watch: {
'$route': function () {
console.log('route changed');
this.fetchResourceForm();
}
},
created() {
this.fetchResourceForm();
},
methods: {
async fetchResourceForm() {
let route;
if (this.resourceId !== null) {
route = Cms.route('cms.api.forms.show', {
resource: this.resource,
id: this.resourceId
});
} else {
route = Cms.route('cms.api.forms.new', {resource: this.resource});
}
const response = await api(route);
this.fields = response.data.data.fields;
},
async submitResourceForm() {
const formData = this.getFormData();
try {
const foo = {
...Cms.route('cms.api.forms.store', _.pickBy({
resource: this.resource,
id: this.resourceId
})),
data: formData
};
const response = await api(foo);
this.$emit('success', response.data.data);
} catch (error) {
if (error.response.status === 422) {
this.validationErrors = error.response.data.errors;
Cms.flash('error', 'There are validation errors in the form.')
}
}
}
}
}
</script>
Cms.route方法确实生成api路由,与vue-router无关。
答案 0 :(得分:2)
从任何父组件中观察路由器。
watch:{
`$route`:function(route){
if(route.name === 'users.create'){
this.fetchData(route.params.id);
}
}
},
methods:{
fetchData:function(id){
// fetch your data corresponding to the id
// save the response to store using `commit`.
// this.$store.commit('SET_FIELDS',response.data.data.fields);
}
}
然后在商店中初始化mutation
和state
const state = {
fields:{}
}
const mutations = {
SET_FIELDS:(state,value)=>state.fields = value;
}
在ResourceForm
组件内部,您可以使用store
方法从computed
获取数据。
computed:{
fields:function(){
return this.$store.state.fields;
}
}
fields
值将在更改路线时实时呈现。
答案 1 :(得分:1)
我认为您可以将用户置于vuex
状态,并在两个组件中都使用此状态。或通过beforeEnter
钩子启动请求
答案 2 :(得分:1)
您需要的是In Component Guards,因为这些导入方法在组件中可用,因为您将导入的视图直接传递给了vue-router
:
{
path: '/admin/users',
name: 'users.index',
component: Index // <-- makes Component Guards available in './views/Index.vue'
},
替换:
created() {
this.fetchResourceForm();
}
具有:
// Fires if you are already on a DYNAMIC route when a uri parameter like :id changes
// This will for example run if you navigate from `/admin/users/123` to `/admin/users/456`
beforeRouteUpdate(to, from, next) {
this.fetchResourceForm();
next()
},
// Fires if you switch between different router entries.
// When you navigate from `/something` to `/another-path
beforeRouteEnter(to, from, next) {
this.fetchResourceForm();
next()
},
但是,如果要在路由器视图内的组件中获取数据,则需要watch
,就像其他人建议的那样,但是为什么不将数据作为prop
传递呢?
答案 3 :(得分:0)
我发现了问题。 它与该功能无关,但与生成api路由的组件有关。 如果有人在vue-router中遇到此问题,@ Rijosh的解决方案将起作用。