知识点


vue-router

Vue Router是vue官方的路有管理器,它和Vue.js的核心深度集成,让构建单页面应用变的易如反掌

安装: vue add router

核心步骤:

  • 步骤一:使用vue-router插件,router.js

    1. import Router from 'vue-router'
    2. Vue.use(Router)
  • 步骤二:创建router实例,router.js

    1. export default new Router({...})
  • 步骤三:在根组件添加该实例 main.js

    1. import router from './router';
    2. new Vue({router,}).$mount(#app);
  • 步骤四:添加路由视图,app.vue

    1. <router-view></router-view>
  • 导航

    1. <router-link to="/">home</router-link>
    2. <router-link to="/about">about</router-link>
    1. this.$router.push('/');
    2. this.$router.push('/about')

vue-router源码实现

单页面应用程序,url发生变化,不能刷新,显示对应视图内容。

需求分析

  • spa页面不能刷新
  1. hash #about
  2. histort api /about
  • 根据uri显示对应内容
  1. router-view
  2. 数据响应式
  3. current变量持有uri地址,一旦变化,动态重新执行render

任务

  • 实现一个插件
    • 实现VueRouter类
      1. 1. 处理路由选项
      2. 1. 监控url变化,haschange方法
      3. 1. 响应整个变化
    • 实现install方法
      1. 1. $router注册
      2. 1. 两个全局组件

      实现一个插件:创建VueRouter类和install方法

      创建kvue-router.js ```vue let Vue; //引用构造函数,VueRouter中要使用

//保存选项 class VueRouter{ constructor(options){ this.$options = options;

//监控url变化 定义响应式属性current const initial = window.location.hash.slice(‘1’) || ‘’ //从#后开始截取 Vue.util.defineReactive(this,’current’,initial); //将current值响应式 window.addEventListener(‘haschange’,this.onHasChange.bind(this))

}

onHasChange(){ this.current = window.location.hash.slice(1); } }

//插件需要实现install方法 VueRouter.install = function(_vue){ //引用构造函数,VueRouter中要使用 Vue =_vue;

//任务一,挂载$router Vue.mixin({ beforeCreate(){ //只有根组件拥有router选项 if(this.$options.router){ Vue.prototype.$router = this.$options.router } } }) }

//任务二,实现两个全局组件router-link和router-view Vue.component(‘router-link’,Link); Vue.component(‘router-view’,View);

export default VueRouter

问题:为什么要用混入的形式 因为Vue.use在前,Router实例创建在后,而install逻辑需要使用该实例

  1. <a name="Zs8ew"></a>
  2. ### 创建router-view router-link
  3. 创建Krouter-link.js
  4. ```vue
  5. export default {
  6. props:{
  7. to:string,
  8. requried:true
  9. }
  10. render(h){
  11. // return '<a herf={'#'+this.to}{this.$slots.default}</a>'
  12. return h('a',{
  13. attrs:{
  14. href="#" +this.to
  15. }
  16. },[
  17. this.$slots.default;
  18. ])
  19. }
  20. }
  21. }

创建krouter-view.js
动态获取对应组件,krouter-view.js

  1. export default{
  2. render(h){
  3. //动态获取对应组件
  4. let comonent = null;
  5. //通过在vue实例的router options选项中,寻找当前path对应的组件
  6. const route = this.$router.options.route.find(route=>{
  7. route.path === this.$router.current;
  8. if(route){
  9. component = route.component;
  10. return h(component);
  11. }
  12. })
  13. }
  14. }

Vuex

vuex集中式存储管理应用的所有组件的状态,并以响应的规则保证状态以可预测的方式发生改变
vuex.png

使用vuex

  1. vue add vuex

核心概念

  • state状态,数据
  • mutations更新状态数据
  • actions异步操作数据
  • store包含以上数据的容器

状态-state

state保存应用状态

  1. export default Vuex.store({
  2. state:{
  3. counter:0
  4. }
  5. })

状态变更-mutations

mutations用于修改状态

  1. export default Vuex.store({
  2. mutations:{
  3. add(state){
  4. state.counter++;
  5. }
  6. }
  7. })

派生状态-getters

从state派生出新状态,类似计算属性

  1. export default new Vuex.store({
  2. getters:{
  3. doubuleCouter(state){
  4. //计算属性
  5. return state.counter * 2;
  6. }
  7. }
  8. })

动态-actions

添加业务逻辑,类似于controller

  1. export default new Vuex.store({
  2. actions:{
  3. add({commit}){
  4. setTimeOut(()=>{
  5. commit('add');
  6. },500)
  7. }
  8. }
  9. })

测试代码

  1. <p @click="$store.commit('add')">counter:{{$store.state.couter}}</p>
  2. <p @click="$store.dispatch('add')">async counter:{{$store.state.couter}}</p>
  3. <p>double counter:{{$store.getters.doubleCounter}}</p>

Vuex解析原理

任务分析

  • 实现插件
    • 实现store类
      1. 维持一个响应式的state
      2. 实现commit
      3. 实现dispatch
      4. 实现getters
    • 挂载store

      初始化:store声明,install实现,kvuex.js; ```vue let vue;

class Store{ // 设置默认值 construtor(options={}){ this._vm = new Vue({data:{ $$state:options.state; }})

保存用户的mutaions选项 this._mutations = options.mutations || {}; this._actions = options.actions || {};

//实现action,根据用户传入type获取并执行对应action //同时把action也绑了,因为action可以互调 绑定commit上下文否则action中调用commit可能会出问题 const store = this; const {commit ,action} = store;

this.commit = function boundCommit(type,payload){ commit.call(store,type,payload); }

this.action = function boundAction(type,payload){ action.call(store,type,payload); } }

commit(type,payload){ 获取type对应的mutaion this.entry = this._mutations[type]; if(!entry){ console.log(‘unknow mutation type’) return; } 指定上下文为store实例 传递state给mutation entry(this.state,payload); }

dispatch(type,payload){ 获取用户编写的type对应的action const entry = this._actions[type]; if(!entry){ console.error(unknow action type) return; } //异步结果处理常常需要返回promise return entry(this,payload); }

//设置一个存取器 get(){ returen this._vm.data.$$state; }

set(v){ console.log(‘warnning to set state’); } }

function install(_vue){ Vue = _vue; 挂载store,与挂在router一样,use在前,Store创建在后,而在install Vue.mixin({ beforeCreate(){ if(this.$options.store){ Vue.prototype.$store = this.$options.store; } } }) }

export default {Store,install}; ```