欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue个人学习总结——vue-router与vuex

程序员文章站 2024-03-03 20:22:52
...

vue-router vuex

vue-router

  • 一般作用于vue单页面应用,通过url与组件配合进行

  • 一般与vue-cli配合,模块化分层构建应用

  • html

    • <!-- 使用 router-link 组件来导航. -->
      <!-- 通过传入 `to` 属性指定链接. -->
      <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
      <!-- to='/foo'会跳转对应的组件 也可用写成 :to='{name:Foo}' 即对应的组件组件名 -->
      <router-link to="/foo">Go to Foo</router-link>
      
      <!-- 路由出口 -->
      <!-- 路由匹配到的组件将渲染在这里 -->
      <!-- 使用vue-cli搭建应用时,该出口一般放在根组件App.vue中或嵌套路由的组件中 -->
      <router-view></router-view>
      
  • js

    • main.js

      • 根组件中引入路由
      // 引入组件路由实例配置
      import router from '@/router';
      
      const app = new Vue({
      	router,
      }).$mount('#app')
      
    • 组件内

      • 可以通过this.$router 访问路由器, this.$route 访问当前路由

      • 响应路由参数的变化

        • 路由跳转后对应组件不变化时,例如参数路由,vue为了高效,组件实例会复用即不再渲染一次,因此会造成路由参数变化不会被响应

        • 可以利用watch监测$route对象的变化,做出响应

          const User = {
            template: '...',
            watch: {
              $route(to, from) {
                // 对路由变化作出响应...
              }
            }
          }
          

          或路由守卫

          const User = {
            template: '...',
            beforeRouteUpdate (to, from, next) {
              // react to route changes...
              // don't forget to call next()
            }
          }
          
      • 编程式的导航

        • router.push(location, onComplete?, onAbort?)

          • this.$router.push

          • 这个方法会向 history 栈添加一个新的记录

          • 点击 <router-link :to="..."> 在内部调用 router.push(...)

          • // 字符串
            router.push('home')
            
            // 对象
            router.push({ path: 'home' })
            
            // 命名的路由
            router.push({ name: 'user', params: { userId: '123' }})
            
            // 带查询参数,变成 /register?plan=private
            router.push({ path: 'register', query: { plan: 'private' }})
            
          • 注意: 如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1 -> /users/2),你需要使用 beforeRouteUpdate来响应这个变化 (比如抓取用户信息)。

    • router/index.js 组件路由配置文件

      • // 注册
        Vue.use( VueRouter );
        // 路由实例
        const  router = new VueRouter({
        	// 路由模式 默认是hash,还有history
        	// 两种模式均使得url跳转页面不会重新加载
        	// 	history模式需要后台服务器支持,需要增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
        	mode:'history',
        	// 路由映射	
        	 routes:[
        	 	{
        	 		path: '/',				// 路径
                    name: 'Main',			// 路径名--非必须项
              		component: Main			// 对应显示的组件名称
                    beforeEnter:(to, from, next)=>{
        				//...				// 在路由内配置独享的导航守卫
                 	}
        	 	}{
        	 		path: '/user/:id',		// 动态路由,参数id值会被设置到 this.$route.params
                    name: 'User',
                    props: true,			// 把路由中的 prarms 转成(注入)到组件的 props 中
                    component: User
                 	children:[				// 嵌套子路由
                 		{
                 			path:'profile',	//当 /user/:id/profile 匹配成功,嵌套路由不加 / ,如果嵌套路由path为空则为默认路由,
                 			name:'profile',
                 			component:UserProfile
                 		}
             		]
        	 	},
            	{
                    path: '*',				// 匹配所有路由,即找不到对应路由时就会匹配该路由
                    component:Error			// 一般是显示404错误的组件
                }{
            		path: '/detail',
                 	components: {			// 命名视图,同时 (同级) 展示多个视图组件,而不是嵌套展示
                        default: Foo,		// <router-view> 不加属性name时默认default
                        a: Bar,				// <router-view name='a' >
                        b: Baz
                    },
                    props:{					// 对于包含命名视图的路由,必须分别为每个命名视图添加 `props` 选项:
                        default:true,
                        a:false,
                        b:false,
                    }
            	}
        	 	
        	 ]
        });
        
      • 导航守卫

        • vue-router提供路由守卫:全局的, 单个路由独享的, 或者组件级的。

        • 参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

        • 全局

          • 前置守卫

            • 使用 router.beforeEach 注册一个全局前置守卫,调用在导航未确认,仅有将进入的路由对象,将进入的路由的组件均未解析

            • const router = new VueRouter({ ... })
              
              router.beforeEach((to, from, next) => {
                // ...
              })
              
            • 三个参数:

              • to: Route: 即将要进入的目标 路由对象
              • from: Route: 当前导航正要离开的路由对象
              • next: Function: 调用代表当前钩子resolve。执行效果依赖 next 方法的调用参数。
                • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
                • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
                • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。与router.pushI(...)跳转的规则一致
                • next(error): (2.4.0+) 传入一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError()注册过的回调。

              确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。

          • 解析守卫

            • 使用 router.beforeResolve 注册一个全局解析守卫
            • 用法与前置守卫类似,唯一区别是解析守卫是在导航未确认,同时进入的路由所有组件内守卫和异步路由组件被解析之后调用
          • 后置守卫

            • 使用 router.afterEach 注册一个全局后置守卫
            • 顾名思义在导航确认后被调用
            • 不接受next()参数,不改变导航本身
        • 路由独享

          • 配置路由时加入导航守卫beforeEnter
      • 只有一个守卫

    • 组件内

      • 与其他钩子用法相似

      • 存在beforeRouteEnter,beforeRouteUpdate (2.2 新增),beforeRouteLeave三个守卫钩子

        • const Foo = {
            template: `...`,
            beforeRouteEnter (to, from, next) {
              // 在渲染该组件的对应路由被 confirm 前调用
              // 不!能!获取组件实例 `this`
              // 因为当守卫执行前,组件实例还没被创建
              // 可以通过给next()传递回调访问组件实例
              // 唯一个一个支持回调的守卫  
              next(vm=>{
                //...
              })
            },
            beforeRouteUpdate (to, from, next) {
              // 在当前路由改变,但是该组件被复用时调用
              // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
              // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
              // 可以访问组件实例 `this`
            },
            beforeRouteLeave (to, from, next) {
              // 导航离开该组件的对应路由时调用
              // 可以访问组件实例 `this`
            }
          }
          
    • 完整的导航

      • 触发导航
        • 当前失活组件beforeRouteLeave
        • 全局 beforeEach
          • (如是复用组件 beforeRouteUpdate )
        • 路由配置 beforeEnter
        • 解析异步路由组件
        • 新**组件beforeRouteEnter
          • 全局beforeResolve
      • 导航确认
        • 全局 afterEach
        • DOM更新
          • 新组件的beforeRouteEnternext()回调
  • 路由懒加载

    • 把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件

      结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

      //  Vue
      const Foo = () => Promise.resolve({ /* 组件定义对象 */ })
      
      import('./Foo.vue') // 返回 Promise
      

      ​ 以往

      • import Main from '@/views/Main.vue';
        

        改为

      • const Main = () => import('@/views/Main.vue')
        

vuex

  • vuex可以解决组件之间的通信包括父子通信、跨级通信、兄弟通信、路由视图级别通信

    • 即对于多个视图依赖于同一状态或者来自不同视图的行为需要变更同一状态的场景
    • vuex即把需要共享的状态抽离在全局中,这样在任何的组件中都可以访问到其状态或者提交改变其状态
  • 是为vue.js应用开发提供的状态管理模式

  • 包含

    • state,驱动应用的数据源;
    • view,以声明方式将 state 映射到视图;
    • actions,响应在 view 上的用户输入导致的状态变化。
    • vue个人学习总结——vue-router与vuex
  • 使用

    • main.js

      import store from '@/store';
      
      new Vue({
        store,				// 在根组件注入,就可以在全局使用this.$store
        render: h => h(App),
      }).$mount('#app')
      
    • store/index.js vuex配置文件

      import Vue from 'vue'
      import Vuex from 'vuex'
      
      Vue.use(Vuex)
      
      const store = new Vuex.Store({
        // 储存状态数据,也为响应式
        state: {
         
        },
        // 类似于计算属性,需带一个参数表示自身
        getters:{
            sometodo:state => {
      	  	return ...
            }
        }
          
        // 组件中提交修改状态的方法,固定需要第一个参数,第二负载参数可续
        // mutation 必须是同步函数
        mutations: {
          somefn(state, payload){
          	// ...
      	}
        }// 修改状态的异步方法,默认返回Promise
        // Action 提交的是 mutation,而不是直接变更状态。
        actions:{
          
        }
      });
      export default store;
      
    • 组件中

      // 使用计算属性响应式获取状态
      computed:{
        some(){
              return this.$store.state.some;
        }
      }
      
      // vuex提供了mapState函数,适用一个组件需要获取多个状态,有多种用法
      import { mapState } from 'vuex'
      
      export default {
        // ...
        computed: mapState({
          // 箭头函数可使代码更简练
          count: state => state.count,
      
          // 传字符串参数 'count' 等同于 `state => state.count`
          countAlias: 'count',
      
          // 为了能够使用 `this` 获取局部状态,必须使用常规函数
          countPlusLocalState (state) {
            return state.count + this.localCount
          }
        })
      }
      
      // fn为mutations中定义的方法,payload为可选传值参数
      this.$store.commit('fn',payload);
      
      // 分发actions
      this.$store.dispatch('increment')