Vue系列:路由与vuex认知

1.vue 路由

1.1实现router-link组件 (主要返回一个a标签)

/**router-link.js**/

export default {
  props:{
    to:{
      type:String,
      required:true
    }
  },
  render(h){
    return h("a",{attrs:{herf:`#${this.to}`}},this.$slots.default) // 三个参数,第一个是a标签,第二个是参数,第三个是children
  }
}

1.2实现router-view组件, (渲染匹配到的内容)

/**router-view.js**/

export default {
        render(h) {
            // 标记自己是router-view 组件
            this.$vnode.data.routerView = true;

            // 标记路由深度
            let depth = 0;
            let parent = this.$parent;
            while (parent) {
                const vnodeData = parent.$vnode && parent.$vnode.data
                if (vnodeData) {
                    if (vnodeData.routerView) {
                        depth++
                    }
                }
                parent = parent.$parent
            }



            // 获取path对应的component
            // const item = this.$router.$options.routes.find(({ path }) => path === this.$router.current);

            const item = this.$router.matched[depth]
            if (!item) {
                return h('div', '')
            }
            return h(item.component)
        }
 }

1.3 vue-router (实现vue-router功能)

/**vue-router.js**/

import link from './router-link.js'
import view from './router-view.js'

let Vue;

class VueRouter {
    constructor(options) {
        this.$options = options;

        // 需要创建响应式属性
        // Vue.util.defineReactive(this, 'current', window.location.hash.slice(1))
        this.current = window.location.hash.slice(1);
        Vue.util.defineReactive(this, 'matched', [])

        // 监听url变化
        window.addEventListener('hashchange', () => {
            console.log(window.location.hash)
            this.current = window.location.hash.slice(1)
            this.matched = []

            this.match()
        })
    }

    match(routers) {
        routers = routers || this.$options.routes

        for (const router of routers) {
            if (router.path === '/' && this.current === '/') {
                this.matched.push(router)
            } else if (router.path !== '/' && this.current.indexOf(router.path) === 0) {
                this.matched.push(router)
                if (router.children)
                    this.match(router.children)
                return;
            }

        }
    }
}

VueRouter.install = function(_vue){
  Vue  = _vue;

  Vue.mixin({
     beforeCreate(){
      if(this.$options.router){
        Vue.prototype.$router = this.$options.router // 将vue-router挂载到Vue实例上
      }
     }
   })

  // 注册两个组件
  Vue.component('router-link',link)
  Vue.component('router-view',view)
}

export default VueRouter

1.4 配置路由表

/**index.js**/

import Vue from 'vue'
import VueRouter from './vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
    children: [
      {
        path: '/about/test',
        name: 'test',
        component: {
          render(h) {
            return h('div', 'test page')
          },
        }
      }
    ]
  }
]

const router = new VueRouter({
  routes
})

export default router

1.5使用

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false
Vue.prototype.$create = create;

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

2.vuex

2.1实现

/**vuex.js**/

class Store {
    constructor(options) {
        this._getters = options.getters
        this._mutations = options.mutations
        this._actions = options.actions

        // 定义computed选项
        const computed = {};
        this.getters = {}; // 暴露给用户

        const stroe = this;
        Object.keys(this._getters).forEach(key => {
            const fn = stroe._getters[key]

            computed[key] = function () { // 增加computed 需要的参数
                return fn(stroe.state);
            }

            Object.defineProperty(stroe.getters, key, {
                get: () => stroe.state[key]
            })
        })

        this.state = new Vue({
            data: options.state,
            computed: computed,
        })



        // 绑定commit actions 的上下文为store示例
        this.commit = this.commit.bind(this);
        this.dispatch = this.dispatch.bind(this);
    }

    // 类型 ,负载
    commit(type, payload) {
        const entry = this._mutations[type]
        if (entry) {
            entry(this.state, payload);
        }
    }

    dispatch(type, payload) {
        const entry = this._actions[type]
        if (entry) {
            entry(this, payload);
        }
    }
}

function install(_Vue) {
    Vue = _Vue

    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store
            }
        },
    })
}

// Vuex
export default {
    Store,
    install
}

2.2配置

import Vue from 'vue'
import Vuex from './vuex.js'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    add(state) {
      state.count++
    }
  },
  actions: {
    asyncAdd({ commit }) {
      setTimeout(() => {
        commit("add")
      }, 2000)
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  },
  modules: {
  }
})

2.3 使用

import Vue from 'vue'
import App from './App.vue'
import store from './Store'


new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

/**
    <P @click="$store.commit('add')">add:{{ $store.state.count }}</P>
    <P @click="$store.dispatch('asyncAdd')"
      >asyncAdd:{{ $store.state.count }}</P
    >
    <P>doubleCount:{{ $store.getters.doubleCount }}</P>
**/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值