-
Vue-router
安装vue-router
Vue.use ->
创建路由实例对象->
挂载Vue
实例上
router-link
跳转router-view
展示页面配置路由
import Vue from 'vue' import VueRouter from 'vue-router' //路由懒加载引入 const Home = () => import('../components/Home.vue') //挂载路由 Vue.use(VueRouter) const router = [ { path: '/home',//路径 meta: { //元数据 }, component: Home,//组件 }, ] const Router = new VueRouter({ routes: router, mode: 'history'//路由模式 history hash }) export default Router
路由Props
<!-- to --> 表示目标路由的链接 <router-link to="home">Home</router-link> <!-- replace--> 设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(), 于是导航后不会留下 history 记录。 <router-link :to="{ path: '/abc'}" replace></router-link> tag 想要渲染的标签 <router-link :to="{ path: '/abc'}" replace></router-link> active-class 设置链接激活时使用的 CSS 类名 <router-link :to="{ path: '/abc'}" replace></router-link> exact 精确匹配模式 <router-link :to="{ path: '/abc'}" replace></router-link>
全局导航守卫
为什么使用路由导航守卫:如果需要切换路由同时并动态修改网页标题在每一个页面中去写会不好维护,可以直接使用导航守卫统一去做修改.
//路由对象router //beforEach 前置守卫 || 钩子(hook 回调) router.beforEach((to,form,next)=>{ /* 要去的路由 to = { path:'/home', component:Home, //源数据 meta:{ title:'首页' } } 现在的路由 from next() 执行下一步 */ //全局网页title的改变 document.title=to.meta.title //进行下一步 next() }) //afterEach 后置守卫 || 钩子(hook) router.afterEach((to, from) => { //跳转后回调 })
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫:
这些守卫与全局前置守卫的方法参数是一样的。const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
组件内的守卫
beforeRouteEnter beforeRouteUpdate (2.2 新增) beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` } }
完整的导航解析流程
导航被触发。
在失活的组件里调用beforeRouteLeave
守卫。
调用全局的beforeEach
守卫。
在重用的组件里调用beforeRouteUpdate
守卫 (2.2+)。
在路由配置里调用beforeEnter
。
解析异步路由组件。
在被激活的组件里调用beforeRouteEnter
。
调用全局的beforeResolve
守卫 (2.5+)。
导航被确认。
调用全局的afterEach
钩子。
触发DOM
更新。
调用beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。keep-alive
使用keep-alive包裹动态组件时,会缓存组件实例,而不是销毁它们
被keep-alive包裹的组件会生效activated
(组件活跃状态)和deactivated
(组件不活跃状态)这两个生命周期钩子函数
Props:excloud "不包含的组件", incloud,"包含的组件"
<transition> <keep-alive> <router-view></router-view> </keep-alive> </transition>
-
Vuex
专门为Vue开发的状态管理工具(模式)
流程 :Vuex采用MVC模式中的Model层,规定所有的数据必须通过action—>mutaion—>state这个流程进行来改变状态的
组件触发事件dispatch->action接收事件通过请求->通过Mutation更新->state 状态改变了通过双向绑定原理生成虚拟Dom和真实Dom树对比差异,然后更新视图viewVuex 核心概念
### 'state' 单一状态树 ### 'Getter' 可以认为是store 的计算属性 const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } 通过属性访问 store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] Getter 也可以接受其他 getter 作为第二个参数 getters: { // ... doneTodosCount: (state, getters) => { return getters.doneTodos.length } } 通过方法访问 你也可以通过让 getter 返回一个函数,来实现给 getter 传参。 在你对 store 里的数组进行查询时非常有用 getters: { // ... getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false } }) ### 'Mutation' 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler) Mutation 需遵守 Vue 的响应规则 既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。 这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项: 1.最好提前在你的 store 中初始化好所有所需属性。 2.当需要在对象上添加新属性时,你应该 使用 Vue.set(obj, 'newProp', 123), 或者 以新对象替换老对象。例如,利用对象展开运算符 (opens new window)我们可以这样写: state.obj = { ...state.obj, newProp: 123 } Mutation 必须是同步函数 使用常量替代 Mutation 事件类型 // mutation-types.js export const SOME_MUTATION = 'SOME_MUTATION' // store.js import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名 [SOME_MUTATION] (state) { // mutate state } } }) const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } }) 你不能直接调用一个 'mutation handler' 你需要以相应的 type 调用 store.commit 方法: store.commit('increment') 提交参数'(Payload)' // ... mutations: { increment (state, n) { state.count += n } } store.commit('increment', 10) 对象风格的提交方式 store.commit({ type: 'increment', amount: 10 }) ### 'Action' 'Action' 提交的是 'mutation',而不是直接变更状态,'可以包含任意异步操作' 注册一个简单的 'action' const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } }) Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象 因此你可以调用 context.commit 提交一个 mutation 或者通过 context.state 和 context.getters 来获取 state 和 getters。 使用Action store.dispatch('increment') // 以载荷形式分发 store.dispatch('incrementAsync', { amount: 10 }) // 以对象形式分发 store.dispatch({ type: 'incrementAsync', amount: 10 }) // 以promise的形式返回Action actions: { actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } } store.dispatch('actionA').then(() => { // ... }) ### 'Module' 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。 当应用变得非常复杂时,store 对象就有可能变得相当臃肿 为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。 每个模块拥有自己的 state、mutation、action、getter 甚至是嵌套子模块——从上至下进行同样方式的分割: const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态 模块的局部状态 const moduleA = { state: () => ({ count: 0 }), mutations: { increment (state) { // 这里的 `state` 对象是模块的局部状态 state.count++ } }, getters: { doubleCount (state) { return state.count * 2 } } } 同样,对于模块内部的 action,局部状态通过 context.state 暴露出来 根节点状态则为 context.rootState: const moduleA = { // ... actions: { incrementIfOddOnRootSum ({ state, commit, rootState }) { if ((state.count + rootState.count) % 2 === 1) { commit('increment') } } } } 对于模块内部的 getter,根节点状态会作为第三个参数暴露出来: const moduleA = { // ... getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } } '模块的命名空间' 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块 能够对同一 mutation 或 action 作出响应。 如果希望你的模块具有更高的封装度和复用性, 你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后, 它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如: const store = new Vuex.Store({ modules: { account: { namespaced: true, // 模块内容(module assets) state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响 getters: { isAdmin () { ... } // -> getters['account/isAdmin'] }, actions: { login () { ... } // -> dispatch('account/login') }, mutations: { login () { ... } // -> commit('account/login') }, // 嵌套模块 modules: { // 继承父模块的命名空间 myPage: { state: () => ({ ... }), getters: { profile () { ... } // -> getters['account/profile'] } }, // 进一步嵌套命名空间 posts: { namespaced: true, state: () => ({ ... }), getters: { popular () { ... } // -> getters['account/posts/popular'] } } } } } })
单页面状态管理
多个组件共享状态
Vue相关知识点
最新推荐文章于 2024-08-19 13:55:31 发布