Vue插件

92 阅读2分钟

插件基础

1. Vue.use去使用一个插件,并且会执行install方法

如果use传入的参数是一个方法且方法没有install方法,就执行这个方法

    var a = function () {
      console.log(1)
    }
    Vue.use(a)
    // 控制台打印1

如果use传入的参数有install方法,就执行install方法

    var a = function () {
       console.log(1)
    }
    a.install = function () {
       console.log('install')
    }
    Vue.use(a)
    // 控制台打印install

2.Vue.mixin往vue的全局中混入自定义的操作

在install方法使用mixin混入全局变量

    // 混入
    var a = function () {
      console.log(1)
    }
    a.install = function (vue) {
      vue.mixin({
        data: function () {
          return {
            c: 123456
          }
        }
      })
    }
    Vue.use(a)
    // 使用
    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
        <p>{{c}}</p>
      </div>
    </template>

混入全局方法

    // 混入
    var a = function () {
      console.log(1)
    }
    a.install = function (vue) {
      vue.mixin({
        data: function () {
          return {
            c: 123456
          }
        },
        methods: {
            globalMethod: function () {
                console.log('this is global method')
            }
        }
      })
    }
    Vue.use(a)
    // 使用
    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
        <p>{{c}}</p>
      </div>
    </template>
    
    <script>
    export default {
      name: 'test',
      data () {
        return {
          msg: 'test'
        }
      },
      mounted () {
          this.globalMethod()
      }
    }
    // 控制台打印this is global method

混入生命周期

    var a = function () {
      console.log(1)
    }
    a.install = function (vue) {
      vue.mixin({
        data: function () {
          return {
            c: 123456
          }
        },
        created (this) {
          console.log('i am create')
          console.log(this) // this 指向当前vue实例
        }
      })
    }
    Vue.use(a)
    // 每个vue实例打印一次i am create

3.vue工具方法

warn  extend  mergeOptions  defineReactive

defineReactive: 监听对象的属性变化

    var a = function () {
      console.log(1)
    }
    var test = {
      a: 1
    }
    setTimeout(function () {
      test.a = 4444
    }, 5000)
    a.install = function (vue) {
      // vue工具方法
      console.log(vue.util)
      vue.util.defineReactive(test, 'a')
      vue.mixin({
        data: function () {
          return {
            c: 123456
          }
        },
        beforeCreate () {
          this.test = test
        },
        created () {
          console.log('i am create')
        }
      })
    }

4. 实现简单的vue-router

代码实现

    class HistoryRoute {
      constructor () {
        // 需要监听的当前路径
        this.current = null
      }
    }
    class vueRouter {
      // options: 路由配置
      constructor (options) {
        this.mode = options.mode || 'hash'
        this.routes = options.routes || []
        this.routersMap = this.createMap(this.routes)
        this.history = new HistoryRoute()
        this.init()
      }
      init () {
        if (this.mode === 'hash') {
          // 自动加#号
          if (location.hash !== '') {
            location.hash = '/'
          }
          // location.hash ? '' : location.hash = '/'
          // 初始化加载
          window.addEventListener('load', () => {
            this.history.current = location.hash.slice(1)
          })
          // 监听hash变化
          window.addEventListener('hashchange', () => {
            console.log('change')
            this.history.current = location.hash.slice(1)
          })
        }
      }
      // 路由数组改为对象
      createMap (routes) {
        return routes.reduce((memo, current) => {
          memo[current.path] = current.component
          return memo
        }, {})
      }
    }
    vueRouter.install = function (vue) {
      // 注意判断插件是否已经注册
      if (vueRouter.install.installed) {
        return false
      }
      vueRouter.install.installed = true
      vue.mixin({
        beforeCreate () {
          if (this.$options && this.$options.router) {
            this._root = this
            this._router = this.$options.router
            vue.util.defineReactive(this, 'current', this._router.history)
          } else {
            this._root = this.$parent._root
          }
          // $router私有 外部只能访问不能修改
          Object.defineProperty(this, '$router', {
            get () {
              return this._root._router
            }
          })
        }
      })
      // 渲染对应组件
      vue.component('router-view', {
        render (h) {
          let current = this._self._root._router.history.current
          let routerMap = this._self._root._router.routersMap
          return h(routerMap[current])
        }
      })
    }
    export default vueRouter

使用

    import Vue from 'vue'
    import Router from '../myrouter'
    import HelloWorld from '@/components/HelloWorld'
    import Test from '@/components/test'
    
    Vue.use(Router)
    
    export default new Router({
      routes: [
        {
          path: '/',
          name: 'HelloWorld',
          component: HelloWorld
        },
        {
          path: '/test',
          name: 'Test',
          component: Test
        }
      ]
    })