有没有办法在路由更改时重新渲染组件?我正在使用 Vue Router 2.3.0,并且在多个路由中使用相同的组件。它第一次工作正常,或者如果我导航到不使用该组件的路线,然后转到使用该组件的路线。我正在传递道具的不同之处,就像这样
{
name: 'MainMap',
path: '/',
props: {
dataFile: 'all_resv.csv',
mapFile: 'contig_us.geo.json',
mapType: 'us'
},
folder: true,
component: Map
},
{
name: 'Arizona',
path: '/arizona',
props: {
dataFile: 'az.csv',
mapFile: 'az.counties.json',
mapType: 'state'
},
folder: true,
component: Map
}
然后我使用道具加载新地图和新数据,但地图保持与首次加载时相同。我不确定发生了什么事。
该组件如下所示:
data() {
return {
loading: true,
load: ''
}
},
props: ['dataFile', 'mapFile', 'mapType'],
watch: {
load: function() {
this.mounted();
}
},
mounted() {
let _this = this;
let svg = d3.select(this.$el);
d3.queue()
.defer(d3.json, `static/data/maps/${this.mapFile}`)
.defer(d3.csv, `static/data/stations/${this.dataFile}`)
.await(function(error, map, stations) {
// Build Map here
});
}
您可能想向
<router-view>
添加 :key 属性,如下所示:
<router-view :key="$route.fullPath"></router-view>
这样,一旦路径发生变化,Vue Router 就会重新加载组件。如果没有密钥,它甚至不会注意到某些内容发生了变化,因为正在使用相同的组件(在您的例子中是 Map 组件)。
我在
vue-router
文档中找到了这个东西,它被称为In Component Guards。通过它的描述,它确实适合您的需求(实际上也是我的需求)。所以代码应该是这样的。
export default () {
beforeRouteUpdate (to, from, next) {
// called when the route that renders this component has changed,
// but this component is reused in the new route.
// For example, for a route with dynamic params `/foo/:id`, when we
// navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
// will be reused, and this hook will be called when that happens.
// has access to `this` component instance.
const id = to.params.id
this.AJAXRequest(id)
next()
},
}
如你所见,我只是添加了一个
next()
函数。希望这对您有帮助!祝你好运!
以下是我的旧答案。
只为“进步”而保存
我解决这个问题的方法是观察
$route
属性。to
和 from
。
watch: {
'$route'(to, from) {
const id = to.params.id
this.AJAXRequest(id)
}
},
此问题的替代解决方案可以在更多情况下处理这种情况。
首先,你不应该自己打电话给
mounted()
。将您在 mounted
中所做的事情抽象为可以从 mounted
调用的方法。其次,Vue 将在可能的情况下尝试重用组件,因此您的主要问题可能是 mounted
只被触发一次。相反,您可以尝试使用 updated
或 beforeUpdate
lifecycle 事件。
const Map = {
data() {
return {
loading: true,
load: ''
}
},
props: ['dataFile', 'mapFile', 'mapType'],
methods:{
drawMap(){
console.log("do a bunch a d3 stuff")
}
},
updated(){
console.log('updated')
this.drawMap()
},
mounted() {
console.log('mounted')
this.drawMap()
}
}
这里有一个小例子,不是画 d3 的东西,而是展示当你交换路线时
mounted
和 updated
是如何被触发的。打开控制台,您将看到 mounted
只被触发一次。
您可以使用此代码:
watch: {
$route(to, from) {
// react to route changes...
}
}
是的,我也遇到了同样的问题,并通过以下方式解决了;
产品详情.vue
data() {
return {
...
productId: this.$route.params.productId,
...
};
},
methods: {
...mapActions("products", ["fetchProduct"]),
...
},
created() {
this.fetchProduct(this.productId);
...
}
fetchProduct
功能来自Vuex
商店。当点击另一个产品时,路由参数会被 productId
更改,但 component
不会重新渲染,因为 created
生命周期钩子在初始化阶段执行。
当我在父组件
router-view
文件上添加 app.vue
上的键时
app.vue
<router-view :key="this.$route.path"></router-view>
现在对我来说效果很好。希望这会对 Vue 开发者有所帮助!
我遇到了同样的问题,但略有不同。我刚刚在道具上添加了一个手表,然后在道具更改上重新启动了 fetch 方法。
import { ref, watch } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import Page from './content/Page.vue';
import Post from './content/Post.vue';
const props = defineProps({ pageSlug: String });
const pageData = ref(false);
const pageBodyClass = ref('');
function getPostContent() {
let postRestEndPoint = '/wp-json/vuepress/v1/post/' + props.pageSlug;
fetch(postRestEndPoint, { method: 'GET', credentials: 'same-origin' })
.then(res => res.json())
.then(res => {
pageData.value = res;
})
.catch(err => console.log(err));
}
getPostContent();
watch(props, (curVal, oldVal) => {
getPostContent();
});
watch(pageData, (newVal, oldVal) => {
if (newVal.hasOwnProperty('data') === true && newVal.data.status === 404) {
pageData.value = false;
window.location.href = "/404";
}
});
路由器-index.js
{
path: "/:pageSlug",
name: "Page",
component: Page,
props: true,
},
{
path: "/product/:productSlug",
name: "Product",
component: Product,
},
{
path: "/404",
name: "404",
component: Error404,
}
对组件进行包装,这将通过使用“key”属性强制重新加载原始组件。如果分配了唯一的“键”值,Vue 不会重用 DOM 的组件/部分。
例如,您有 UserList 组件,每次路由发生变化时,您都希望完全重新加载该组件(通过调用 onMounted)。
使用以下内容制作包装器 UserListRefresh
<script lang="ts" setup> import { useRoute } from "vue-router"; import UsersList from "./UsersList.vue"; const route=useRoute(); </script> <template> <UsersList :key="route.fullPath"></UsersList> </template>
现在将此 UserListRefresh 分配给路由而不是原始的 UserList。这样就可以解决问题,导航到具有不同 :groupId 部分的相同路径,您将看到该组件正在重建。
{
path: "/administrative/users/:groupId",
component: UsersListRefresh,
name: 'UsersList',
meta: {
title: 'User List of Group',
},
},