手牵手教你写 Vue 插件

栏目: JavaScript · 发布时间: 5年前

内容简介:上一篇文章,我们介绍了如何构建一个 react 插件,今天我们说说如何构建 vue 插件由于与上一篇 react 插件文章使用的是相同的结构,代码测试、持续集成及发布 npm 包也都是一个套路,这里就不再敖述。 下面主要说下不同的地方,let's start :blush:写 vue 插件稍微复杂一点 :cry:,根据官网的案例,我们需要提供一个包含 install 方法的对象或者一个函数(传送门),供 Vue.use 调用注册你的插件

上一篇文章,我们介绍了如何构建一个 react 插件,今天我们说说如何构建 vue 插件

准备工作

由于与上一篇 react 插件文章使用的是相同的结构,代码测试、持续集成及发布 npm 包也都是一个套路,这里就不再敖述。 下面主要说下不同的地方,let's start :blush:

  1. 开发依赖包
{
    "devDependencies": {
        "@babel/core": "^7.0.0",
        "@babel/preset-env": "^7.0.0",
        "babel-loader": "^8.0.2",
        "chai": "^4.2.0",
        "coveralls": "^3.0.2",
        "css-loader": "^1.0.0",
        "jest": "^23.6.0",
        "style-loader": "^0.23.1",
        "vue": "^2.5.21",
        "vue-loader": "^15.5.0", // 解析 SFC 文件
        "vue-style-loader": "^4.1.2",
        "vue-template-compiler": "^2.5.21", // vue-loader 的同步依赖 
        "webpack": "^4.17.2",
        "webpack-cli": "^3.1.0"
    },
}
复制代码
  1. webpack 配置
const path = require('path');
const { VueLoaderPlugin } = require("vue-loader");

module.exports = {
    mode: "production", // 生产模式
    entry: { // 入口
        "YanProgress": path.resolve(__dirname, './src/index.js')
    },
    output: { // 出口
        path: path.resolve(__dirname, './dist'),
        filename: '[name].min.js',
        publicPath: "./dist/",
        libraryTarget: 'umd', // 按 UMD 模式打包
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    // 模板编译过程中,编译器可以将某些特性转换为 require 调用
                    transformAssetUrls: {
                        video: ['src', 'poster'],
                        source: 'src',
                        img: 'src',
                        image: 'xlink:href' // SVG
                    }
                },
                // 只命中src目录里的js文件,加快 Webpack 搜索速度
                include: path.resolve(__dirname, "./src"),
            },
            {
                test: /\.js$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    },
                ],
                // 只命中src目录里的js文件,加快 Webpack 搜索速度
                include: path.resolve(__dirname, "./src/"),
            },
            {

                test: /\.css$/,
                loader: "style-loader!css-loader"
            }
        ]
    },
    plugins: [
        // vue-loader **这个插件是必须的!**它的职责是将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块。
        new VueLoaderPlugin
    ],
    resolve: { // 省略文件后缀时,默认按下面的配置取
        extensions: ['.js', '.vue'],
    },
    externals: { // 不把 vue 打包进去
        vue: 'vue',
    }
};
复制代码

编写插件

写 vue 插件稍微复杂一点 :cry:,根据官网的案例,我们需要提供一个包含 install 方法的对象或者一个函数(传送门),供 Vue.use 调用注册你的插件

  • 写法一
import Component from './YanProgress.vue'; // 这个就是你平时写的 SFC 组件

// 这里要导出一个包含 install 方法的对象
let plugin = { // 这里要导出一个 install 方法
    install(Vue,options) { 
        // 这里写你的代码,你可以全局注册组件,也可以写全局指令,也可以扩展 Vue 的方法
        // 1. 全局组件
        Vue.component('yan-progress',Component); 
        // 2. 全局方法或属性
        Vue.myGlobalMethod = function () {
            // 逻辑...
        }
        // 3. 全局指令
        Vue.directive('my-directive', {
            bind (el, binding, vnode, oldVnode) {
                // 逻辑...
            }
        })
        // 4. 注入组件
        Vue.mixin({
            created: function () {
                // 逻辑...
            }
        })
        // 5. 添加实例方法
        Vue.prototype.$myMethod = function (methodOptions) {
            // 逻辑...
        }
    }
};

if (window && window.Vue) { // 如果是渐进式开发(script 引入简单粗暴的开发方式),需要自动注册你的插件
    window.Vue.use(plugin);
}

export default plugin;

复制代码
  • 写法二
import Component from './YanProgress.vue'; // 这个就是你平时写的 SFC 组件

// 或者这里也可以写成函数
function plugin(Vue,options) { 
        // 这里写你的代码,你可以全局注册组件,也可以写全局指令,也可以扩展 Vue 的方法
        Vue.component('yan-progress',Component); 
    }
};

if (window && window.Vue) { // 如果是渐进式开发(script 引入简单粗暴的开发方式),需要自动注册你的插件
    window.Vue.use(plugin);
}

export default plugin;
复制代码

这样写的原因是,下面 源码 伺候:smile:

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) { // 在这里哦,可以传对象,也可以传函数
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) { // 避免重复注册插件
      return this
    }

    // additional parameters
    const args = toArray(arguments, 1)
    args.unshift(this)
    if (typeof plugin.install === 'function') { // 如果是带有 install 方法的对象
      plugin.install.apply(plugin, args) // 不改变插件的 this(这里的 this 还是指向插件对象本身)
    } else if (typeof plugin === 'function') { // 如果是函数
      plugin.apply(null, args) // 不改变插件的 this(这里应该是指向window,在浏览器非严格模式下)
    }
    installedPlugins.push(plugin)
    return this
  }
}
复制代码

开源贡献

拥抱开源,这样才能让社区,乃至行业发展更有动力,哎,似曾相识的赶脚,:joy:

注:例如,你的 star 是对我最大的鼓励,是支持我继续开源的动力,:smile:

  • awesome-vue 社区 awesome-vue
  • 其他社区,可以到 Github 探索

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入浅出Web设计(中文版)

深入浅出Web设计(中文版)

(美)瓦特罗尔、(美)西罗托 / O'Reilly Taiwan公司 / 东南大学出版社 / 2010-11 / 99.00元

你将从《深入浅出Web设计(中文版)》学到什么?你曾经希望看看书就能学到真正的网站设计吗?曾经想过该如何同时达成让网站看起来美观,又能有效率地沟通信息,还要通过可访问性与可用性的策略吗?《深入浅出Web设计》正是精通上述主题的秘笈。我们将学到如何设计一个绝佳、用户友好的网站,上谈客户需求,下说手绘分镜表,乃至完成在线所需的HTML与css主文件……而且会有一个真正可以运作的网站!一起来看看 《深入浅出Web设计(中文版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具