vuex-router-sync 是做什么用的?
what is vuex-router-sync for?
据我所知,vuex-router-sync
仅用于同步 route
与 vuex store
,开发人员可以按如下方式访问 route
:
store.state.route.path
store.state.route.params
不过,我也可以用this.$route
来处理route
,这样更简洁。
什么时候需要使用store中的路由,什么场景下需要vuex-router-sync?
这是我的两分钱。如果您无法弄清楚它在项目中的用例,则不需要导入 vuex-router-sync
,但是当您尝试在 vuex
中使用 route
对象时可能需要它方法(this.$route
在 vuex 的领域中效果不佳)。
我想在这里举个例子。
假设您想在一个组件中显示一条消息。你想在几乎每个页面都显示类似 Have a nice day, Jack
的消息,除了用户浏览首页时应该显示 Welcome back, Jack
的情况。
在vuex-router-sync
的帮助下,您可以轻松实现。
const Top = {
template: '<div>{{message}}</div>',
computed: {
message() {
return this.$store.getters.getMessage;
}
},
};
const Bar = {
template: '<div>{{message}}</div>',
computed: {
message() {
return this.$store.getters.getMessage;
}
}
};
const routes = [{
path: '/top',
component: Top,
name: 'top'
},
{
path: '/bar',
component: Bar,
name: 'bar'
},
];
const router = new VueRouter({
routes
});
const store = new Vuex.Store({
state: {
username: 'Jack',
phrases: ['Welcome back', 'Have a nice day'],
},
getters: {
getMessage(state) {
return state.route.name === 'top' ?
`${state.phrases[0]}, ${state.username}` :
`${state.phrases[1]}, ${state.username}`;
},
},
});
// sync store and router by using `vuex-router-sync`
sync(store, router);
const app = new Vue({
router,
store,
}).$mount('#app');
// vuex-router-sync source code pasted here because no proper cdn service found
function sync(store, router, options) {
var moduleName = (options || {}).moduleName || 'route'
store.registerModule(moduleName, {
namespaced: true,
state: cloneRoute(router.currentRoute),
mutations: {
'ROUTE_CHANGED': function(state, transition) {
store.state[moduleName] = cloneRoute(transition.to, transition.from)
}
}
})
var isTimeTraveling = false
var currentPath
// sync router on store change
store.watch(
function(state) {
return state[moduleName]
},
function(route) {
if (route.fullPath === currentPath) {
return
}
isTimeTraveling = true
var methodToUse = currentPath == null ?
'replace' :
'push'
currentPath = route.fullPath
router[methodToUse](route)
}, {
sync: true
}
)
// sync store on router navigation
router.afterEach(function(to, from) {
if (isTimeTraveling) {
isTimeTraveling = false
return
}
currentPath = to.fullPath
store.commit(moduleName + '/ROUTE_CHANGED', {
to: to,
from: from
})
})
}
function cloneRoute(to, from) {
var clone = {
name: to.name,
path: to.path,
hash: to.hash,
query: to.query,
params: to.params,
fullPath: to.fullPath,
meta: to.meta
}
if (from) {
clone.from = cloneRoute(from)
}
return Object.freeze(clone)
}
.router-link-active {
color: red;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuex/dist/vuex.js"></script>
<div id="app">
<p>
<router-link to="/top">Go to Top</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
fiddle here
如您所见,组件与 vuex
和 vue-router
的逻辑很好地分离。
如果您不关心当前路由与 vuex 的 getter.
返回值之间的关系,这种模式有时会非常有效。
我在学习Vue的时候看到了这个帖子。补充一些我对问题的理解。
Vuex 为 Vue 应用程序定义了一种状态管理模式。我们没有定义组件 props 并在所有地方通过 props 传递共享状态,而是使用集中式存储来组织多个组件共享的状态。对状态突变的限制使得状态转换更清晰,更容易推理。
理想情况下,如果提供的商店状态相同,我们应该获得/构建一致(或相同)的视图。但是,由多个组件共享的路由器打破了这一点。如果我们需要推断页面呈现的原因,如果我们从 this.$router
属性派生视图,则需要检查存储状态和路由器状态。
vuex-router-sync
是将路由器状态同步到中央状态存储的助手。现在所有的视图都可以从状态存储中构建,我们不需要检查 this.$router
.
请注意 route
状态是不可变的,我们应该通过 $router.push
或 $router.go
调用 "change" 它的状态。将商店中的某些操作定义为:
可能会有所帮助
// import your router definition
import router from './router'
export default new Vuex.Store({
//...
actions: {
//...
// actions to update route asynchronously
routerPush (_, arg) {
router.push(arg)
},
routerGo (_, arg) {
router.go(arg)
}
}
})
这包装了存储操作中的 route
更新,我们可以完全摆脱组件中的 this.$router
依赖关系。
据我所知,vuex-router-sync
仅用于同步 route
与 vuex store
,开发人员可以按如下方式访问 route
:
store.state.route.path
store.state.route.params
不过,我也可以用this.$route
来处理route
,这样更简洁。
什么时候需要使用store中的路由,什么场景下需要vuex-router-sync?
这是我的两分钱。如果您无法弄清楚它在项目中的用例,则不需要导入 vuex-router-sync
,但是当您尝试在 vuex
中使用 route
对象时可能需要它方法(this.$route
在 vuex 的领域中效果不佳)。
我想在这里举个例子。
假设您想在一个组件中显示一条消息。你想在几乎每个页面都显示类似 Have a nice day, Jack
的消息,除了用户浏览首页时应该显示 Welcome back, Jack
的情况。
在vuex-router-sync
的帮助下,您可以轻松实现。
const Top = {
template: '<div>{{message}}</div>',
computed: {
message() {
return this.$store.getters.getMessage;
}
},
};
const Bar = {
template: '<div>{{message}}</div>',
computed: {
message() {
return this.$store.getters.getMessage;
}
}
};
const routes = [{
path: '/top',
component: Top,
name: 'top'
},
{
path: '/bar',
component: Bar,
name: 'bar'
},
];
const router = new VueRouter({
routes
});
const store = new Vuex.Store({
state: {
username: 'Jack',
phrases: ['Welcome back', 'Have a nice day'],
},
getters: {
getMessage(state) {
return state.route.name === 'top' ?
`${state.phrases[0]}, ${state.username}` :
`${state.phrases[1]}, ${state.username}`;
},
},
});
// sync store and router by using `vuex-router-sync`
sync(store, router);
const app = new Vue({
router,
store,
}).$mount('#app');
// vuex-router-sync source code pasted here because no proper cdn service found
function sync(store, router, options) {
var moduleName = (options || {}).moduleName || 'route'
store.registerModule(moduleName, {
namespaced: true,
state: cloneRoute(router.currentRoute),
mutations: {
'ROUTE_CHANGED': function(state, transition) {
store.state[moduleName] = cloneRoute(transition.to, transition.from)
}
}
})
var isTimeTraveling = false
var currentPath
// sync router on store change
store.watch(
function(state) {
return state[moduleName]
},
function(route) {
if (route.fullPath === currentPath) {
return
}
isTimeTraveling = true
var methodToUse = currentPath == null ?
'replace' :
'push'
currentPath = route.fullPath
router[methodToUse](route)
}, {
sync: true
}
)
// sync store on router navigation
router.afterEach(function(to, from) {
if (isTimeTraveling) {
isTimeTraveling = false
return
}
currentPath = to.fullPath
store.commit(moduleName + '/ROUTE_CHANGED', {
to: to,
from: from
})
})
}
function cloneRoute(to, from) {
var clone = {
name: to.name,
path: to.path,
hash: to.hash,
query: to.query,
params: to.params,
fullPath: to.fullPath,
meta: to.meta
}
if (from) {
clone.from = cloneRoute(from)
}
return Object.freeze(clone)
}
.router-link-active {
color: red;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuex/dist/vuex.js"></script>
<div id="app">
<p>
<router-link to="/top">Go to Top</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
fiddle here
如您所见,组件与 vuex
和 vue-router
的逻辑很好地分离。
如果您不关心当前路由与 vuex 的 getter.
我在学习Vue的时候看到了这个帖子。补充一些我对问题的理解。
Vuex 为 Vue 应用程序定义了一种状态管理模式。我们没有定义组件 props 并在所有地方通过 props 传递共享状态,而是使用集中式存储来组织多个组件共享的状态。对状态突变的限制使得状态转换更清晰,更容易推理。
理想情况下,如果提供的商店状态相同,我们应该获得/构建一致(或相同)的视图。但是,由多个组件共享的路由器打破了这一点。如果我们需要推断页面呈现的原因,如果我们从 this.$router
属性派生视图,则需要检查存储状态和路由器状态。
vuex-router-sync
是将路由器状态同步到中央状态存储的助手。现在所有的视图都可以从状态存储中构建,我们不需要检查 this.$router
.
请注意 route
状态是不可变的,我们应该通过 $router.push
或 $router.go
调用 "change" 它的状态。将商店中的某些操作定义为:
// import your router definition
import router from './router'
export default new Vuex.Store({
//...
actions: {
//...
// actions to update route asynchronously
routerPush (_, arg) {
router.push(arg)
},
routerGo (_, arg) {
router.go(arg)
}
}
})
这包装了存储操作中的 route
更新,我们可以完全摆脱组件中的 this.$router
依赖关系。