Vue-plugin(插件)

一、插件的基本使用

1.1 初识插件
Vue.use()做了什么事情?

Vue.use的作用是注册一个Vue插件(注册组件), Vue.use必须在new Vue之前使用
什么时候需要定义插件?

当某一个组件或者功能经常需要被使用到时, 我们就可以将这个组件或者功能定义成一个插件
例如: 网络加载指示器
4.插件通常用来为 Vue 添加全局功能

插件的功能范围没有严格的限制——一般有下面几种:

添加全局方法或者 property。如:vue-custom-element

添加全局资源:指令/过滤器/过渡等。如 vue-touch

通过全局混入来添加一些组件选项。如 vue-router

添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

1.2 插件开发流程

通过 vue create name 创建好vue项目后

在src目录下新建一个名为plugins的文件夹并在该文件夹里面新建一个loading的目录,在loading目录下新建一个名为loading.vue和index.js的文件
plugins/loading/loading.vue

<template>
    <div class="container">
        <div class="loading"></div>
        <p class="title">正在加载...</p>
    </div>
</template>
 
<script>
    export default {
        name: "Loading"
    }
</script>
 
<style scoped>
    .container{
        width: 200px;
        height: 200px;
        border-radius: 20px;
        background: rgba(0,0,0,.5);
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
    }
 
    .container .loading{
        width: 100px;
        height: 100px;
        border-radius: 50%;
        border: 5px solid #fff;
        margin: 20px auto;
        border-right-color: #4fc08d;
        animation: loading  2s linear infinite;
    }
 
    .container .title  {
        text-align: center;
        color: #fff;
    }
 
    @keyframes loading {
        from{
            transform: rotate(0deg);
        }
        to{
            transform: rotate(360deg);
        }
    }
</style>

plugins/loading/index.js

import Vue from "vue"
import Loading from "./loading"
 
export default {
     /*
    * 如果要将一个组件封装成一个插件,那么必须提供一个install方法,必须在install方法中注册当前的这个组件
    */
    install() {
        Vue.component(Loading.name,Loading);
    }
}

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
// import Loading from "./components/Loading";
import Loading from "./plugins/loading/index";
// 注册为全局组件
// import Loading from "./components/Loading";
// Vue.component(Loading.name,Loading)
//或通过use的方式,但是先要将组件先封装成一个插件后才能
Vue.use(Loading)
 
Vue.config.productionTip = false
 
new Vue({
  render: h => h(App),
}).$mount('#app')

App.vue

<template>
  <div id="app">
    <Loading></Loading>
  </div>
</template>
 
<script>
    // import Loading from "./components/Loading";
 
export default {
  name: 'App',
  components: {
    // Loading
  },
  data:function(){
     return{ 
 
     }
  },
   methods:{
 
   }
}
</script>
 
<style scoped>
</style>

在这里插入图片描述
将以上代码进行优化改造:

plugins/loading/loading.vue

<template>
    <div class="container" v-show="isShow">
        <div class="loading"></div>
        <p class="title">{{title}}</p>
    </div>
</template>
 
<script>
    export default {
        name: "Loading",
        data(){
            return {
                title: '正在加载...',
                isShow: false
            }
        },
    }
</script>
 
<style scoped>
    .container{
        width: 200px;
        height: 200px;
        border-radius: 20px;
        background: rgba(0,0,0,.5);
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
    }
 
    .container .loading{
        width: 100px;
        height: 100px;
        border-radius: 50%;
        border: 5px solid #fff;
        margin: 20px auto;
        border-right-color: #4fc08d;
        animation: loading  2s linear infinite;
    }
 
    .container .title  {
        text-align: center;
        color: #fff;
    }
 
    @keyframes loading {
        from{
            transform: rotate(0deg);
        }
        to{
            transform: rotate(360deg);
        }
    }
</style>

plugins/loading/index.js

import Loading from "./loading"
 
export default {
    /*
    * 如果要将一个组件封装成一个插件,那么必须提供一个install方法,必须在install方法中注册当前的这个组件
    */
    install(Vue,Options) {
        //1.根据组件生成构造函数
        let LoadingConstructor = Vue.extend(Loading)
 
        //2.根据构造函数创建实例对象
        let LoadingInstance = new LoadingConstructor();
 
        //3.随便创建一个标签(元素)
        let oDiv= document.createElement('div');
 
        //4.将创建好的标签添加到页面上
        document.body.appendChild(oDiv);
 
        //5.将创建好的实例对象挂载到创建好的元素上
        LoadingInstance.$mount(oDiv);
 
        // console.log(Options);
        // console.log(LoadingInstance.title);
        //添加初始化值
        setTimeout(function () {
            if(Options&&Options.title!==null&&Options.title!==undefined){
                LoadingInstance.title=Options.title;
            }
        },2000);
 
        //添加全局方法
        Vue.showLoading=function () {
            LoadingInstance.isShow = true;
        };
 
        Vue.hiddenLoading=function () {
            LoadingInstance.isShow = false;
        }
 
        //添加实例方法(局部)
        Vue.prototype.$showLoading=function () {
            LoadingInstance.isShow = true;
        };
        Vue.prototype.$hiddenLoading=function () {
            LoadingInstance.isShow = false;
        };
    }
}

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import Loading from "./plugins/loading/index";
//或通过use的方式,但是先要将组件先封装成一个插件后才能
//只要调用use方法,就会去调用其对应的install方法
Vue.use(Loading,{
  title: '加载完成'
})
 
Vue.config.productionTip = false
 
new Vue({
  render: h => h(App),
}).$mount('#app')

App.vue

<template>
  <div id="app">
      <button @click="myFn1">显示</button>
      <button @click="myFn2">隐藏</button>
  </div>
</template>
 
<script>
// import Vue from 'vue'
 
export default {
  name: 'App',
  components: {
  },
  data:function(){
     return{
     }
  },
   methods:{
       myFn1(){
           // Vue.showLoading();//全局方法
           this.$showLoading();
       },
       myFn2(){
           // Vue.hiddenLoading();//全局方法
           this.$hiddenLoading();
       }
   }
}
</script>
 
<style scoped>
</style>

在这里插入图片描述
二、插件示例
2.1 自定义 Toast 提示框

App.vue

<template>
  <div id="app">
    <button @click="toastHandle">提示框</button>
  </div>
</template>
 
<script>
export default {
  name: 'App',
  components: {
    
  },
  methods: {
    toastHandle() {
      this.$toast("toast提示框",{
        duration:10000,
        defaultType:"warning"
      });
    },
  }
}
</script>
 
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import Toast from "./plugins/toast"
import "./plugins/toast/toast.css"
 
Vue.use(Toast);
Vue.config.productionTip = false
 
new Vue({
    render: h => h(App),
}).$mount('#app')

plugins/toast/toast.css

.vue-toast{
    position: fixed;
    color: #fff;
    width: 50%;
    height: 150px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 20px;
    background:rgba(0, 0, 0, 0.6);
    border-radius: 10px;
    top: 50%;
    left: 50%;
    margin-left: -25%;
    margin-top: -25%;
    z-index:999;
}
 
.toast-success{
    color: #fff;
}
 
.toast-danger{
    color: #ff0000;
}
 
.toast-warning{
    color: #ff0;
}

plugins/toast/index.js

var Toast = {}
Toast.install = function(Vue) {
 
    let opt = {
        duration: 3000,
        defaultType: "success"
    }
 
    Vue.prototype.$toast = (tips, type) => {
        if (type.duration) {
            opt.duration = type.duration
        }
        if (type.defaultType) {
            opt.defaultType = type.defaultType
        }
        let toastTpl = new Vue({
            render() {
                return ( 
                    <div class = {
                        ['vue-toast', 'toast-' + opt.defaultType] } > { tips } </div>
                )
            }
        })
 
        let tpl = toastTpl.$mount().$el; // 创建实例,挂载到文档中
        document.body.appendChild(tpl);
        setTimeout(function() {
            document.body.removeChild(tpl)
        }, opt.duration)
    }
 
    ["success", "danger", "warning"].forEach(type => {
        Vue.prototype.$toast[type] = (tips) => {
            return Vue.prototype.$toast(tips, type)
        }
    })
 
}
 
export default Toast

在这里插入图片描述
下面是之前多的一个项目里面用到的插件,结合自定义指令

import Tree from './src/tree.vue';

/* istanbul ignore next */
Tree.install = function(Vue) {
  Vue.component(Tree.name, Tree);
};

export default Tree;

highlight.js  代码高亮指令
import Hljs from 'highlight.js';
import 'highlight.js/styles/tomorrow-night.css'; // 代码高亮风格,选择更多风格需导入 node_modules/hightlight.js/styles/ 目录下其它css文件

let Highlight = {};
// 自定义插件
Highlight.install = function (Vue) {
    // 自定义指令 v-highlight
    Vue.directive('highlight', {
        // 被绑定元素插入父节点时调用
        inserted: function(el) {
            let blocks = el.querySelectorAll('pre code');
            for (let i = 0; i < blocks.length; i++) {
                Hljs.highlightBlock(blocks[i]);
            }
        },
        // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
        componentUpdated: function(el) {
            let blocks = el.querySelectorAll('pre code');
            for (let i = 0; i < blocks.length; i++) {
                Hljs.highlightBlock(blocks[i]);
            }
        }
    })
};

export default Highlight;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值