上回说了组件(vue组件开发练习--焦点图切换)的一个练习项目,此次换下口味,说下vue的插件练手的项目。相对于如今以前的焦点图切换的组件,这个可能就更简单了,基本就是熟悉下插件开发的步骤就能够了!这个项目,我更建议你们动手练习了,这个弹窗比以前的焦点图更加的实用性,也更经常使用。同时也能让你们熟悉下vue的插件开发的流程。代码一样,我会上传到github(ec-dialog),须要的能够直接去看代码!css
建议
1.下面的步骤,最好在本身本地上跑起来,根据文章的步骤,逐步完成,若是只看代码,很容易懵逼的。
2.若是不清楚哪一个代码有什么做用,可能本身调试下,把代码去掉后,看下有什么影响,就很容易想出代码有什么做用了!
仍是一个很简单的目录,各个目录不知道有什么用的,能够移步去看我上一篇文章。和组件开发的目录相比,区别就在于src/js/components
这个文件夹上。html
首先,先弄src/js/components/alert
这个组件。仍是同样,,先在src/js/components/alert/src/main.vue
。输出‘守候’。代码以下vue
<template> <transition name="ec"> <div class="ec"> 守候 </div> </transition> </template> <script> export default { data () { return { name: 'ec-alert', } }, computed: {}, mounted () { }, methods: { } } </script>
而后来到'alert/index.js'
。这个术语叫什么什么文件,我不太清楚,暂时就叫,插件配置文件吧!代码以下(注意看注释)git
import Vue from 'vue' import AlertComponent from './src/main.vue' //合并对象函数,这个方法是会改变,第一个参数的值的 function merge(target) { for (let i = 1, j = arguments.length; i < j; i++) { let source = arguments[i] || {}; for (let prop in source) { if (source.hasOwnProperty(prop)) { let value = source[prop]; if (value !== undefined) { target[prop] = value; } } } } return target; }; let instance; //extend 是构造一个组件的语法器.传入参数,返回一个组件 let AlertConstructor = Vue.extend(AlertComponent); let initInstance = ()=>{ //实例化ConfirmConstructor组件 instance = new AlertConstructor({ el: document.createElement('div') }); //添加到boby document.body.appendChild(instance.$el); } let Alert = (options={}) => { //初始化 initInstance(); // 将单个 confirm instance 的配置合并到默认值(instance.$data,就是main.vue里面的data)中 merge(instance.$data, options); //返回Promise return new Promise((resolve, reject)=>{ instance.show = true; let success = instance.success; let cancel = instance.cancel; instance.success = () => { //先执行instance.success(main.vue里面的success函数) success(); //再执行自定义函数 resolve('ok'); } }); } export default Alert;
而后来到components/js/index.js
这个文件,配置组件和API,代码以下程序员
import alert from './alert/index.js' const install = function(Vue) { //注册全局组件 Vue.component(alert.name, alert) //添加全局API Vue.prototype.$alert = alert } export default install
而后在模板文件,index.html
里面设置一个div,方便挂载测试github
<!DOCTYPE html> <html lang="en"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> </div> </body> </html>
而后在入口文件index.js
里面,使用插件npm
require("./index.html"); //引入sass require("./src/sass/com.scss"); import Vue from 'vue' import dialog from './src/js/components/index'; Vue.use(dialog) let App = new Vue({ el: '#app', data(){ return { 'name': 'index' } }, mounted(){ this.$alert(); } });
而后,命令行 $ npm run dev
,结果完美segmentfault
完成了上一步,这个插件的一大半就算完成了!剩下的工做主要开发的就是在components/../main.vue
这文件开发。
首先,先别急写代码,想一下,一个弹窗大概须要什么字段。sass
参考上面,发现有一个标题,一个内容,一个按钮文字。最后还须要一个变量,控制弹窗是否显示。而后一个点击按钮的操做函数。而后还有样式,大概以下微信
样式这个很少说,其余的字段,一个萝卜一个坑的填进去就好,代码以下
<template> <transition name="ec"> <div v-if="show" class="ec"> <div class="ec-box"> <div class="ec-box-inner"> <div class="ec-title" v-if="title">{{title}}</div> <div class="ec-content">{{content}}</div> </div> <div class="ec-box-buttons"> <span class="ec-btn-success" @click="success">{{submitText}}</span> </div> </div> </div> </transition> </template> <script> export default { data () { return { name:'ec-alert', show: false, title: '提示', content: '', submitText: '肯定', cancelText: '取消' } }, computed: {}, mounted () { }, methods: { success () { this.show = false; } } } </script> <style lang="scss" scoped> .ec { background: rgba(00, 00, 00, .5); position: fixed; left: 0; top: 0; width: 100%; height: 100%; .ec-box { width: 80%; max-width: 400px; top: 200px; position: absolute; left: 0; right: 0; margin: auto; background: #fff; box-sizing: border-box; padding: 20px; border-radius: 6px; } .ec-title { padding-left: 0; margin-bottom: 0; font-size: 16px; font-weight: 700; height: 18px; color: #333; } .ec-content { padding: 14px 0; line-height: 24px; color: #48576a; font-size: 14px; } .ec-box-buttons { text-align: right; } .ec-btn-success { background: #20a0ff; border-color: #20a0ff; display: inline-block; line-height: 1; white-space: nowrap; cursor: pointer; color: #fff; margin: 0; padding: 10px 15px; border-radius: 4px; } .ec-btn-cancel { display: inline-block; line-height: 1; white-space: nowrap; cursor: pointer; background: #fff; border: 1px solid #c4c4c4; color: #1f2d3d; margin: 0; padding: 10px 15px; border-radius: 4px; } } .ec-enter { opacity: 0; .ec-box { transform:scale(0); } } .ec-enter-active { transition: opacity .4s; .ec-box { transition: transform .4s; } } .ec-leave-active{ transition: opacity .2s; .ec-box { transition: transform .2s; } } .ec-leave-active { opacity: 0; } </style>
运行效果
你们知道,在前面步骤,'alert/index.js'
这里就已经返回的一个Promise。因此,用法就是像Promise那样使用!
因此在入口文件,index.js
里面直接写
mounted(){ this.$alert({ title:'提示2', content:'这里是提示内容2' }).then(()=>{ this.name='守候' alert(this.name) }) }
运行效果
仍是那句话,程序员不会知足于现状,只有一种弹窗,怎么够,下面我再增长一种,和上面那个基本同样,就是多了一个取消按钮而已。
这里我就再讲一个简单的栗子,至于弹窗的样式,太多了,我在这里就不展开说了,你们须要的可进行拓展。
首先,建立这个目录(能够直接把alert那个目录拷贝过来,而后再修改几下就完事了)
而后,针对comfirm/src/main.vue
文件,添加下面的代码(下面的代码基本就是从alert/src/main.vue
拷贝过来的,就是增长一个取消按钮的对应一个字段和操做函数)
<template> <transition name="ec"> <div v-if="show" class="ec"> <div class="ec-box"> <div class="ec-box-inner"> <div class="ec-title" v-if="title">{{title}}</div> <div class="ec-content">{{content}}</div> </div> <div class="ec-box-buttons"> <span class="ec-btn-success" @click="success">{{submitText}}</span> <span class="ec-btn-cancel" @click="cancel">{{cancelText}}</span> </div> </div> </div> </transition> </template> <script> export default { data () { return { name:'ec-comfirm', show: false, title: '提示', content: '', submitText: '肯定', cancelText: '取消' } }, computed: {}, mounted () { }, methods: { success () { this.show = false; }, cancel () { this.show = false; } } } </script> <style lang="scss" scoped> .ec { background: rgba(00, 00, 00, .5); position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 9999; .ec-box { width: 80%; max-width: 400px; top: 200px; position: absolute; left: 0; right: 0; margin: auto; background: #fff; box-sizing: border-box; padding: 20px; border-radius: 6px; } .ec-title { padding-left: 0; margin-bottom: 0; font-size: 16px; font-weight: 700; height: 18px; color: #333; } .ec-content { padding: 14px 0; line-height: 24px; color: #48576a; font-size: 14px; } .ec-box-buttons { text-align: right; } .ec-btn-success { background: #20a0ff; border-color: #20a0ff; display: inline-block; line-height: 1; white-space: nowrap; cursor: pointer; color: #fff; margin: 0; padding: 10px 15px; border-radius: 4px; } .ec-btn-cancel { display: inline-block; line-height: 1; white-space: nowrap; cursor: pointer; background: #fff; border: 1px solid #c4c4c4; color: #1f2d3d; margin: 0; padding: 10px 15px; border-radius: 4px; } } .ec-enter { opacity: 0; .ec-box { transform:scale(0); } } .ec-enter-active { transition: opacity .4s; .ec-box { transition: transform .4s; } } .ec-leave-active{ transition: opacity .2s; .ec-box { transition: transform .2s; } } .ec-leave-active { opacity: 0; } </style>
而后就是comfirm/index.js
(也是基本拷贝的,我就截图,告诉你们改哪里吧,这个得稍微细看才知道改哪里)
而后components/index.js
import comfirm from './comfirm/index.js' import alert from './alert/index.js' const install = function(Vue) { //注册全局组件 Vue.component(comfirm.name, comfirm) Vue.component(alert.name, alert) //添加全局API Vue.prototype.$confirm = comfirm Vue.prototype.$alert = alert } export default install
最后在入口文件,index.js
使用
require("./index.html"); //引入sass require("./src/sass/com.scss"); import Vue from 'vue' import dialog from './src/js/components/index'; Vue.use(dialog) let App = new Vue({ el: '#app', data(){ return { 'name': 'index' } }, mounted(){ this.$confirm({ title:'提示', content:'这里是提示内容', submitText:'提交', cancelText:'返回' }).then(()=>{ this.$alert({ title:'提示2', content:'这里是提示内容2' }).then(()=>{ this.name='守候' alert(this.name) }) }).catch((err)=>{ alert(err) }) } });
运行结果,就是这样
一个简单的弹窗就到这里了,很简单,可是在我开发那里仍是能用,能暂时知足。可是这个确定是须要维护的,毕竟不少的项目都须要弹窗。你们也根据本身的须要进行拓展!以上的案例也很简单,容易懂。基本都是记流程。可是这个我很建议你们边动手,边看文章。这个可让本身练习下基于vue开发插件,是一个不错的练习,但愿能帮到你们学习到新的知识!最后,若是以为文章那里写的很差或者写错了,欢迎指出!
-------------------------华丽的分割线--------------------
想了解更多,关注关注个人微信公众号:守候书阁