zoukankan      html  css  js  c++  java
  • 【小慕读书】—— 后台管理系统学习:Vuex 和 Vue-router 进阶

    前言:最近在学习Vue+Element UI+Node.js小慕读书中后台管理系统开发课程,这里对学习过程作个笔记,方便自己和大家翻阅。


     一、Vuex 原理解析

    Vuex 的原理关键:使用 Vue 实例管理状态

    <body>
        <div id="root">{{data}}</div>
        <div id="root2">{{data2}}</div>
        <div id="root3">
          <button @click="change">change</button>
        </div>
        <script>
          function registerPlugin(Vue) {
            const vuex = {}
            vuex._vm = new Vue({     //_vm是Vue实例
              data: {
                message: 'hello vue.js'
              }
            })
            vuex.state = vuex._vm
            vuex.mutations = {
              setMessage(value) {
                vuex.state.message = value
              }
            }
            function init() {
              this.$store = vuex
            }
            Vue.mixin({             //全局的mixin
              beforeCreate: init    
            })
          }
          Vue.use(registerPlugin)
          new Vue({
            el: '#root',
            computed: {
              data() {
                return this.$store.state.message
              }
            }
          })
          new Vue({
            el: '#root2',
            computed: {
              data2() {
                return this.$store.state.message
              }
            }
          })
          new Vue({
            el: '#root3',
            methods: {
              change() {
                const newValue = this.$store.state.message + '.'
                this.$store.mutations.setMessage(newValue)     //Vue响应式 前两个Vue实例的message都会变化
              }
            }
          })
        </script>
      </body>
    

    二、vue-router 实现原理

    vue-router 实例化时会初始化 this.history,不同 mode 对应不同的 history

    constructor (options: RouterOptions = {}) {
        this.mode = mode
        
        switch (mode) {
          case 'history':
            this.history = new HTML5History(this, options.base)
            break
          case 'hash':
            this.history = new HashHistory(this, options.base, this.fallback)
            break
          case 'abstract':
            this.history = new AbstractHistory(this, options.base)
            break
          default:
            if (process.env.NODE_ENV !== 'production') {
              assert(false, `invalid mode: ${mode}`)
            }
        }
    }
    

    这里以 HashHistory 为例,vue-router 的 push 方法实现如下: (实际调用的是Hashhistory的push方法) 

    push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
        // $flow-disable-line
        if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
          return new Promise((resolve, reject) => {
            this.history.push(location, resolve, reject)
          })
        } else {
          this.history.push(location, onComplete, onAbort)
        }
    }
    

    HashHistory 具体实现了 push 方法:  

    function pushHash (path) {
      if (supportsPushState) {
        pushState(getUrl(path))
      } else {
        window.location.hash = path
      }
    }
    

    对路由的监听通过 hash 相应的事件监听实现:  

    window.addEventListener(
      supportsPushState ? 'popstate' : 'hashchange',
      () => {
        const current = this.current
        if (!ensureSlash()) {
          return
        }
        this.transitionTo(getHash(), route => {
          if (supportsScroll) {
            handleScroll(this.router, route, current, true)
          }
          if (!supportsPushState) {
            replaceHash(route.fullPath)
          }
        })
      }
    )
    

    除此之外,vue-router 还提供了两个组件:  

    Vue.component('RouterView', View)
    Vue.component('RouterLink', Link)
    

    三、vue-router 路由守卫

    创建 router.js:  

    import Vue from 'vue'
    import Route from 'vue-router'
    import HelloWorld from './components/HelloWorld'
    
    Vue.use(Route)
    const routes = [
      { path: '/hello-world', component: HelloWorld }
    ]
    const router = new Route({
      routes
    })
    
    export default router
    

    在 main.js 中引用 router,并加入 vue 实例:  

    import router from './router'
    
    new Vue({
      render: h => h(App),
      router
    }).$mount('#app')
    

    四、全局守卫

    进入每一个路由都会触发的钩子函数

    注意:因为写在vue-router中,所以全局守卫都是没有办法获得Vue实例的。

    //router.js
    router.beforeEach((to, from, next) => { //当路由进入之前可以触发的操作 console.log('beforeEach', to, from) next() }) router.beforeResolve((to, from, next) => { //当路由被解析之前被调用 Vue2.5新特性 console.log('beforeResolve', to, from) next() }) router.afterEach((to, from) => { //当路由进入之后可以触发的事件 console.log('afterEach', to, from) })

     整个路由守卫执行是在组件生命周期函数之前的:

     beforeEach(全局守卫)befforeResolve(全局守卫)afterEach(全局守卫)

     beforeCreate、created、beforeMount、mouted

    五、局部守卫

    只适合在当前路由使用,是局部的路由守卫。(写在和组件的生命周期函数同一级)

    1.to:表示当前路由,即要进入的路由

    2.from:表示从哪来的,

    3.next() 表示下一步要干啥,next('/addGoods')就表示下一步,调到路由 /addGoods

    //A.vue
    beforeRouteEnter (to, from, next) { //在需要进入的组件中调用 // 不能获取组件实例 `this`, 因为在组件生命周期beforeCreate之前 console.log('beforeRouteEnter', to, from) next() }, beforeRouteUpdate (to, from, next) { //在复用(更新)的组件中调用 console.log('beforeRouteUpdate', to, from) next() }, beforeRouteLeave (to, from, next) { //在离开的组件中调用 console.log('beforeRouteLeave', to, from) next() }
    •  进入组件:beforeEach(全局守卫)、beforeRouteEnter(局部守卫)、beforeResolve(全局守卫)、afterEach(全局守卫)、beforeCreate、created、beforeMount、mounted
    • 更新组件:beforeEach(全局守卫)、beforeRouteUpdate(局部守卫)、beforeResolve(全局守卫)、afterEach(全局守卫)
    • 离开组件:beforeRouteLeave(局部守卫)、beforeEach(全局守卫)、beforeResolve(全局守卫)、afterEach(全局守卫)、 beforeDestory

    六、路由元信息

    通过 meta 定义路由元信息  

    const routes = [
      { path: '/a', component: A, meta: { title: 'Custom Title A' } }
    ]
    

    使用 meta 信息动态修改标题

    (和路由相关的功能,推荐放在路由的全局守卫中实现)  

    router.beforeEach((to, from, next) => {
      console.log('beforeEach', to, from)
      if (to.meta && to.meta.title) {
        document.title = to.meta.title
      } else {
        document.title = 'default title'
      }
      next()
    })

    七、路由 API

    使用 router.addRoutes 动态添加路由

    使用场景:菜单路由的权限赋值 

    addRoute() {
        this.$router.addRoutes([{
          path: '/b', component: B, meta: { title: 'Custom Title B' },
        }])
    }
    

    此时可以访问到 B 组件  

    <router-link to='/b'>to B</router-link>
    

    注:项目来自慕课网    

    人与人的差距是:每天24小时除了工作和睡觉的8小时,剩下的8小时,你以为别人都和你一样发呆或者刷视频
  • 相关阅读:
    es6字符串扩展(+模板字符串拼接)
    MySQL-技术专区-mysql数据库权限管理
    MySQL-技术专区-数据库权限管理
    开源软件的盈利模式
    分布式-技术专区-Redis分布式锁实现-第二步
    分布式-技术专区-Redis分布式锁实现-第一步
    分布式-技术专区-Redis分布式锁原理实现
    JPA接口整理归纳方法规则
    备份整理-实用归纳
    Zookeeper-技术专区-运作流程分析介绍
  • 原文地址:https://www.cnblogs.com/ljq66/p/14349959.html
Copyright © 2011-2022 走看看