After adding a route to vue3 router. addRoute(), why is the page menu not updated? - vue-router

console.log(router.getRoutes()); The number of arrays is increased by 1, and the menu is not updated
console.log(router.getRoutes()); //This array is 29,
//add route
router.addRoute('xitong2', {
path: '/projectbrowsing/duolianjixitong/xitong2',//
component: () => import('#/views/xitong/systemTabShow.vue'),
name: 'Xitong2',
meta: {
title: t('routers.xtyc'),
query: {
systemId: 'a02'
}
}
})
console.log(router.getRoutes()); //This array is 30,
Prompt
Note that adding routes does not trigger new navigation. That is, the added route will not be displayed unless a new navigation is triggered
Does triggering a new navigation refer to a page jump or something?

Related

Force vue 3 router to got to the same route twice - recognize it as a new event

I use vue 3
I have a view that loads components inside it. Each time you click a text, router.push is called , and loads a component, with some params
click here
<h3 #click="handleClick('intro', 'abc')" >intro</h3>
to load component here
<router-view></router-view>
the click is handled as such
setup(){
const router = useRouter();
const handleClick = (part, term)=>{
router.push({name:part, params: {term}}).catch(err => {});
}
return{handleClick}
}
so router.push loads in <router-view> another smaller component (named intro), according to the router of the app, that is set like so
path: '/book',
name: 'book',
component: book,
children:[
{
path: 'intro/:term',
name: 'intro',
component: Intro
},
]
The component is loaded inside the view and the url is like /book/intro/abc
inside the intro component, to handle the change in the route and scroll down the abc id , I do
const route = useRoute();
let id = false;
let mounted = ref(false);
//grab the term from route, to set it as id and if component is mounted, scroll to id
watchEffect(()=>{
id = route.params.term;
let el = document.getElementById(id);
if (mounted && el) {
el.scrollIntoView({behavior: "smooth"});
id = false;
}
})
//check if mounted and if also id that came from route exists, scroll to id
onMounted(() => {
mounted = true;
let el = document.getElementById(id);
if (id && el) {
el.scrollIntoView({behavior: "smooth"});
id = false;
}
})
ISSUE
This works and is based on the route, to load the component and also set the id where it will scroll to.
But if I scroll to an id, then scroll randomly in the page and then click the same id to scroll, it will NOT scroll to that id again, because the id does not change, so route does not fire another event.
example : The url is /book/intro/abc. If I scroll randomly and then click the abc , url is the same, no event is fired, it will not scroll back to abc again.
How do I fix this? I want to avoid having hashtags or queries or questionmarks in my urls. Ideally I want "clean" urls like /book/part/term and I want to load that part indicated by the url, inside the view, not having all the parts loaded inside the view, as a super long text .
EDIT I also want to avoid reloads
Thanks
You can watch the whole route object and force the router change with the force option.
/* In the template */
<router-link :to="{ path: 'some-path', force: true }">link</router-link>
// In the script
const route = useRoute()
watch(() => route, () => {
console.log('route changed')
}, {
deep: true
})

How update a VUE component changing URL param in current page

In my vue SPA I have a simple router like this:
{path: '/page/:userId', name: 'user', component: user},
Which means an url like http://xxx.xxx/user/1 shows the component user having the content about user 1.
In case on the same page I have some link as
<vue-link :to="{name:'user', params={userId:3}}">
The router update only the URL but the content page (because it assumes the page is the same where I'm at)
My user content loads data using the url params in data and in watch too
data
userId: this.$route.params.userId || 1,
watch
watch: {
userId: function () {
return this.$route.params.userId || 1;
},
How to fix it without using router-view?
Thanks for any suggestion
If I correctly get your problem which is that you are not able to track your route change. You need to watch the route change, whenever your route changed on a same component it should do something.
watch: {
$route() {
this.updatePage(this.$route.params.userId)
}
},
methods: {
updatePage(param) {
// call api / do something
}
}

Vuetify v-select not showing items after full refresh

I have a dialog with a v-select that doesn't show values in the drop down after a full page load. It does work after a hot module reload triggered by modifying the component file.
Using vuetify:
"vuetify": "^1.5.17",
Component contains:
template code:
<v-select
:items="routes"
label="Routes"
multiple
chips
persistent-hint
hint="Send to which routes"
v-model="message.routes"
></v-select>
routes is a computed property:
routes: {
get() {
return this.$store.state.routes
}
}
The data gets downloaded in the created event:
created() {
this.downloadRoutes()
}
This maps to a store method that does an AJAX call that commits the returned list:
downloadRoutes({ commit, state }) {
return new Promise((resolve, reject) => {
commit('SET_LOADING', true)
api.get('/route').then(response => {
var routes = response.data.routes
commit('SET_ROUTES', routes)
commit('SET_LOADING', false)
resolve()
})
.catch(function(error) {
commit('SET_LOADING', false)
reject()
})
})
},
AJAX response is just an array of routes:
{"routes":["Route1","Route2","RouteXX"]}
This I have shown by doing a console.log of the response and the state in the computed routes property.
What am I missing?
It sounds like your problem lies somewhere inside the vue instance lifecycle, i.e. you might call this.downloadRoutes() inside the wrong hook. Do your problem still occure if you try with a hardcoded array of Routes?
Found the problem.
My store is initialised via an initialState function.
export default new Vuex.Store({
state: initialState,
getters: {
......
The initial state function declares all the top level collections used in state.
function initialState() {
return {
fullName: localStorage.fullName,
routes: [] // Was missing
}
Adding routes in that initial state solves the problem.
I think it's because watchers on state are not added when new attributes are added to state.
When I do a full page refresh the routes gets added to state after the select is initialized and so it is not watching for changes. During hot module reload the routes is already in the state and is so picked up by the select.

Click on link changes the url but not the content/data on page

the story:
I am on product page #/product/7 and on the same page I have 4 more products that are similar to the one that is being viewed. All these products have links to their pages:
router-link(:to="{ name: 'product', params: { id: product.id }}" v-text='product.title').
the problem:
When I click on any of the product links, the url changes but the content remains the same. So, if I am on #/product/7 and click on #/product/8 the url only will change. If I navigate from /product/:id page and click on a product it takes me to the right page with proper content.
As you can see on screenshot, current product id is 15, but the content is the one from the id 7, as shown in url at the bottom while I was hovering over the Sleek Silk Shirt product in cart.
Any ideas how to fix this?
You have to update the data of products variable when you change the route as vue optimises page reloads and does not reload in your case if you are on same route.
You can adapt the approach: Fetching Before Navigation described in vue-router docs:
With this approach we fetch the data before actually navigating to the new route. We can perform the data fetching in the beforeRouteEnter guard in the incoming component, and only call next when the fetch is complete:
export default {
data () {
return {
product: {},
error: null
}
},
beforeRouteEnter (to, from, next) {
getProduct(to.params.id, (err, product) => {
if (err) {
// display some global error message
next(false)
} else {
next(vm => {
vm.product = product
})
}
})
},
// when route changes and this component is already rendered,
// the logic will be slightly different.
watch: {
$route () {
this.product = {}
getProduct(this.$route.params.id, (err, product) => {
if (err) {
this.error = err.toString()
} else {
this.product = product
}
})
}
}
}
I couldnt really internalise the above answer with 'getProduct', so to be put simply.
I am using a Store and I needed to watch the $route and when it changes I called my store to dispatch the api call.
watch: {
$route () {
this.$store.dispatch('fetchStudyStandards',
this.$route.params.standardID);
}
}
So basically watch the route and if it changes, re do your api call.

why I change the navigator props execute twice handler?

here is my View to switch page
this.props.navigator.push({
component: QuestionDetail,
passProps: {
id: id,
enteredDetail: function() {
console.log(this)
}
}
});
// in QuestionDetail
render: function() {
this.props.enteredDetail();
....
in Xcode I saw this
RCTJSLog> {"navigator":{},"route":{"passProps":{"id":"1010000002652090"}},"id":"1010000002652090"}
RCTJSLog> {"navigator":{},"route":{"passProps":{"id":"1010000002652090"}},"id":"1010000002652090"}
it appear twice! why?
See this issue:
https://github.com/facebook/react-native/issues/151
in order for the react diffing algorithm to correctly reset properties
back to their default state, we create a single dummy "defaultView"
for every type of view