开发VUE插件详细步骤

一.前置知识

1.混入

见官方文档 https://cn.vuejs.org/v2/guide/mixins.html。

  • 基本示例:
    示例文件结构:
    在这里插入图片描述
    新建一个.js文件,里面定义属性,这里面的属性就是vue的属性,在vue文件中引入这个文件中的属性时也会混合到vue的属性中
export default {
    data: function() {
        return {
            tag: '.js',
            age: 11
        }
    },
    mounted: function() {
        console.log('mixin')
    }
}

在vue文件中引入:

<template>
    <div id="demo-minxin">
        {{tag}} - > {{name}} --> {{age}}
    </div>
</template>

<script>

import DemoMixinData from './DemoMixinData'
export default {
    data () {
        return {
            tag: '.vue',
            name: 'demo'
        }
    },
    mounted () {
        console.log('vue')
    },
    mixins: [DemoMixinData] // 这在个地方引入 mixin ,
}
</script>

<style>

</style>

通过mixins:属性引入,生命周期方法将会先执行混入的,后执行vue文件本身的。其他属性不同的添加,相同的已.vue文件本身为准。

2.render函数

先看看main.js文件中的内容:

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

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

从文件中我们可以看到,首先把Vue实例绑定到#app元素上面,这个#app元素是index.html中的元素,不是App.vue中的元素。再引入 App.vue这个文件,然后再Vue实例中注册这个组件,在把App中的html渲染到Vue实例上。

现在通过render函数改写这个:

import Vue from 'vue'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#myApp',
  render: h => (<div>123</div>)
})

render: h => (<div>123</div>)这里的作用就是括号里面的html。
再看另外一个例子:

Vue.component('MyApp', {
  render: function (createElement) {
    return createElement(
      'h1',   // 标签名称
      '123' // 子元素数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

/* eslint-disable no-new */
new Vue({
  el: '#myApp',
  template: '<MyApp/>'
})

首先通过Vue.component注册一个组件,这个组件通过template: '<MyApp/>'渲染到Vue根实例。render函数用来生成组件中的html内容:

Vue.component('MyApp', {
  render: function (createElement) {
    return createElement(
      'h1',   // 标签名称
      '123' // 子元素数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

再次修改main.js:

import Vue from 'vue'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#myApp',
  render: function (createElement) {
    return createElement(
      'h1',   // 标签名称
      '123' // 内容
    )
  }
})

直接通过render函数渲染。

  • 使用h代替createElement
    在这里插入图片描述
    通过代码的方式去写html标签是很繁琐的,但是 通过上面这种形式可以直接写html标签了:
import Vue from 'vue'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#myApp',
  render: h => (<div>
    <h1>123</h1>
  </div>)
})

3.使用代码注册组件

从上面一节中我们看到,可以通过js代码的方式去注册一个组件。

Vue.component('MyApp', {
  render: function (createElement) {
    return createElement(
      'h1',   // 标签名称
      '123' // 子元素数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

现在我们来改写main.js,用代码来注册一个组件:

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

Vue.config.productionTip = false

Vue.component('MyHeader', {
  render: function(createElement) {
    return createElement ('h1', this.headerTitle)
  },
  data () {
      return {
          headerTitle: 'my header'
      }
  },
  mounted () {
      console.log('mounted')
  }
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: {
    App
  },
  render: h => h(App)
})

代码方式注册组件也能指定data、props和生命周期等这些属性。

4.extend

官方例子:
在这里插入图片描述
先看个例子,main.js中的代码如下:

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

Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: {
    App
  },
  render: h => h(App)
})

let MyVue = Vue.extend({
  template: '<h2>h2 标签 {{name}} </h2>',
  data () {
    return {
      name: 'hello '
    }
  },
  mounted () {
    console.log('extend')
  }
})

new MyVue().$mount(".mine");

通过Vue.extend创建一个Vue子类对象构造器,再通过new MyVue().$mount(".mine");创建这个实例对象,然后挂载到.mine元素上,我在app里面有元素的class属性是mine,所以这个组件会挂载到对应的元素上。(挂载时要保证这个元素被创建了,某种会报错找不到这个元素…,所以才把这个挂载写到App组件被注册之后)

extend还能用作组件上
上面这种方式,我们是在extend里编写模板,我们还能把.vue文件作为参数传入extend函数。

  • 先创建一个.vue文件,作为模板
    TheFooter.vue
<template>
    <div class="footer">
        111
        <h1>{{name}}, {{msg}}</h1>
    </div>
</template>

<script>
export default {
    data () {
        return {
            name: 'footer',
            msg: '这是footer.vue文件'
        }
    }
}
</script>

<style>

</style>

在main.js中使用:

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

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: {
    App
  },
  render: h => h(App)
})

// 构建vue子类构造器
let TheFooterConstructer = Vue.extend(TheFooter)
// 创建实例
let theFooter = new TheFooterConstructer();
theFooter.name = '修改了值得name';
// 这样就挂载到了.mine这个元素上了
theFooter.$mount('.mine')

  • 不依赖现有标签挂载
    从上面的几个例子来看,在挂载组件的时候,页面上一定要有一个供挂载的元素才行,否则就会报错,如果不想依赖现有元素,可以用如下方式创建元素:
import Vue from 'vue'
import App from './App'
import TheFooter from './TheFooter'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: {
    App
  },
  render: h => h(App)
})

// 构建vue子类构造器
let TheFooterConstructer = Vue.extend(TheFooter)
// 创建实例
let theFooter = new TheFooterConstructer();
theFooter.name = '修改了值得name';
// 创建一个div,用来挂载用
let mountElement = document.createElement('div');
// 添加创建的元素到body最后面
document.body.appendChild(mountElement)
// 挂载到创建元素上
theFooter.$mount(mountElement)

通过上面的方式就创建了一个无需在已存在元素上挂载的组件。

二、开发插件

1.插件使用例子

我们先来看下使用element-ui的例子,首先是安装element-ui库(插件)。

cnpm install element-ui -S

然后再项目中使用,main.js:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

分析上面代码我们可以看到import ‘element-ui/lib/theme-chalk/index.css’;这是我们引入的一个全局css样式。import ElementUI from ‘element-ui’; Vue.use(ElementUI);这两句代码是引入element-ui并全局注册的关键代码。

2.插件开发

开发插件

根据上面的例子,我们也来自己开发一个类似使用方法的插件。插件通过两个组件MyHeader导航栏和MyFooter底部栏。
首先在src目录下新建一个目录myui,然后新建两个.vue文件MyHeader.vueMyFooter.vue以及一个js文件myui.js
在这里插入图片描述
MyFooter.vue

<template>
    <div id="myfooter">
        footer
    </div>
</template>

<script>
export default {
    name: 'MyFooter'
}
</script>
<style>
body {
    padding-bottom: 60px;
}
</style>

<style scoped>
#myfooter {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 60px;
    color: aliceblue;
    background: rgb(13, 13, 14);
    line-height: 60px;
    text-align: center;
}
</style>

MyHeader.vue

<template>
    <div id="myheader">
        header
    </div>
</template>

<script>
export default {
    name: 'MyHeader'
}
</script>

<style>
body {
    padding-top: 60px;
}
</style>

<style scoped>
#myheader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 60px;
    color: aliceblue;
    background: rgb(45, 70, 104);
    line-height: 60px;
    text-align: center;
}
</style>

这两个.vue组件最终效果是这样的。
在这里插入图片描述
现在来开发myui.js中的内容了:

import MyFooter from './MyFooter'
import MyHeader from './MyHeader'
// 新建一个对象,也就是开发的插件对象
let myui = {
	// 这个对象必须要有一个 install 方法,而且这个方法第一个参数是Vue实例 
    install (Vue) {
    	// 最vue实例上注册 两个 vue 组件
        Vue.component(MyFooter.name, MyFooter)
        Vue.component(MyHeader.name, MyHeader)
    }
}
// 导出对象
export default myui

好了~,这样一个简单的插件就开发完成了!我们来看看该怎么使用插件?

使用插件

main.js中引入开发的插件:

import Vue from 'vue'
import App from './App'
// 引入插件对象
import MyUI from './myui/myui'

// 使用插件
Vue.use(MyUI)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

App.vue中使用插件:

<template>
  <div id="app">
    <MyHeader></MyHeader>
    <MyFooter></MyFooter>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
</style>

最终结果:
在这里插入图片描述

分析

在main.js中,引入了配置插件的js文件import MyUI from ‘./myui/myui’ ,这个文件中配置了插件信息。
Vue.use(MyUI)这个地方配置实用插件,其实在调用use方法的时候执行的就是myui中对象的install方法,而install方法上的参数Vue就是当前的Vue。在install方法。里面注册了两个组件,实际上也就是用外面的vue注册了两个组件。
*可能有人会想为什么要怎么做,为什么不直接在main.js中直接使用**vue.component()*来注册,非要写个myui.js然后传Vue在注册组件?
嗯~,插件嘛,开发起来就是为了要实现某一功能,提供给别人用的,就像element-ui一样,到时候只需要使用npm 安装到项目中就可以直接使用了,所以呢,需要这样开发。如果只是本身项目自己使用,就没必要这样写了!

修改插件,丰富插件功能

为了丰富插件功能,我们修改一下MyHeader.vue文件中的代码:

<template>
    <div :style="{backgroundColor: bgColor, color: color}" id="myheader">
        {{title}}
    </div>
</template>

<script>
export default {
    name: 'MyHeader',
    data () {
        return {
            title: 'header'
        }
    },
    props: {
        // 背景颜色
        bgColor: {
            type: String,
            default: 'rgb(45, 70, 104)',
            required: false
        },
        // 字体颜色
        color: {
            type: String,
            default: 'white',
            required: true
        }
    },
    methods: {
        // 这个方法用来改变颜色
        changColor(bgColor = null, color = null) {
            if (null !== bgColor || null !== color) {
                this.bgColor = bgColor
                this.color = color
            }
        }
    },
    mounted() {
        console.log('header已被加载')
    }
}
</script>

<style>
body {
    padding-top: 60px;
}
</style>

<style scoped>
#myheader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 60px;
    line-height: 60px;
    text-align: center;
}
</style>

修改后的MyHeadee组件提供了多个属性,data,props,method和mounted,然后也绑定了内联样式,title是header组件显示的文字,bgColor是header组件的背景颜色,color是header组件的文字颜色。

props中的属性可以在使用组件时传入,那么data中的属性和methods中的方法要怎么使用呢??
修改一下MyHeader.vue中的代码:

<template>
    <div :style="{backgroundColor: bgColor, color: color}" id="myheader">
        {{title}}
    </div>
</template>

<script>
export default {
    name: 'MyHeader',
    data () {
        return {
            title: 'header'
        }
    },
    props: {
        // 背景颜色
        bgColor: {
            type: String,
            default: 'rgb(45, 70, 104)',
            required: false
        },
        // 字体颜色
        color: {
            type: String,
            default: 'white',
            required: false
        }
    },
    methods: {
        // 这个方法用来改变颜色
        changColor(bgColor = null, color = null) {
            if (null !== bgColor || null !== color) {
                this.bgColor = bgColor
                this.color = color
            }
        }
    },
    mounted() {
        console.log('header已被加载')
    }
}
</script>

<style>
body {
    padding-top: 60px;
}
</style>

<style scoped>
#myheader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 60px;
    line-height: 60px;
    text-align: center;
}
</style>

基于上面的问题和之前的extend函数,我们对myui.js做如下修改:

import MyFooter from './MyFooter'
import MyHeader from './MyHeader'

let myui = {
    // install 可以接受除 Vue实例以外的参数 在main.js中 Vue.use()时传入
    install (Vue, title = null) {
        Vue.component(MyFooter.name, MyFooter)
        //Vue.component(MyHeader.name, MyHeader)
        // 构造vue子类构造器
        let MyHeaderContructor = Vue.extend(MyHeader)
        // 通过上面的构造器生成 MyHeaderContructor 实例对象,这个对象是可以直接访问组件中的属性的
        let myHeaderInstance = new MyHeaderContructor()

        // 初始化title的值
        if (title !== null) {
            myHeaderInstance.title = title
        }

        // 注册全局方法
        Vue.initMyHeader = function (bgColor, color) {
            myHeaderInstance.bgColor = bgColor
            myHeaderInstance.color = color
        }

        // 添加实例方法
        Vue.prototype.$changeColor = function(bgColor, color) {
            myHeaderInstance.changeColor(bgColor, color)
        }

        // 挂载实例
        let ele = document.createElement('div')
        document.body.appendChild(ele)
        myHeaderInstance.$mount(ele)

    }
}
export default myui

由于MyHeader.vue没有同过注册组件的方式使用的,所以要删除App.vue对MyHeader组件的引用,App.vue中代码如下:

 <template>
  <div id="app">
    <MyFooter></MyFooter>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
</style>

页面效果不变。
在这里插入图片描述

调用方法

myui.js中对象中的install (Vue, title = null) 方法传入了一个title,现在我们通过这个属性来改变页面上header中显示的内容,在main.js中做如下修改,在调用use方法的时候传入一个title属性:


Vue.use(MyUI, "我是插件中的header组件")

使用后的结果,我们发现header上的值也发生了改变:
在这里插入图片描述
然后在myui.js还有这么一个方法

Vue.prototype.$changeColor = function(bgColor, color) {
           myHeaderInstance.changeColor(bgColor, color)
}

这要怎么使用呢??
分析上面方法我们能发现,这个方法**$changeColor是挂载到Vue实例的原型上的,在组件中使用时只需要调用this.\$changeColor ()即可。
现在,我们在
App.vue**中做如下修改:

<template>
  <div id="app">
    <div class="btn">
      <button @click="changeColor('rgb(65, 118, 168)','rgb(19, 18, 18)')">变成蓝色</button>
      <button @click="changeColor('rgb(214, 200, 8)','rgb(19, 18, 18)')">变成黄色</button>
      <button @click="changeColor('rgb(19, 18, 18)','rgb(248, 248, 248)')">变成黑色</button>
      <button @click="changeColor('rgb(126, 124, 124)', 'rgb(248, 248, 248)')">变成灰色</button>
    </div>
    <MyFooter></MyFooter>
  </div>
</template>

<script>

export default {
  name: 'App',
  methods: {
    changeColor(bgColor, color) {
      this.$changeColor(bgColor, color);
    }
  }
}
</script>

<style>
.btn {
  margin: 100px auto 0;
}
</style>

结果,我们点击对应的按钮,就可以操作使header发生改变:
在这里插入图片描述
至此,一个Vue插件就开发完成了,如果想让别人也能用到拟开发的插件,只需要把你开发的插件上传到npm上,别人再从npm上安装下来,就可以愉快的使用了!

如果对您有帮助,就点个赞吧!!欢迎留言评论@_@

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值