上回說了組件(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開發插件,是一個不錯的練習,但願能幫到你們學習到新的知識!最後,若是以爲文章那裏寫的很差或者寫錯了,歡迎指出!
-------------------------華麗的分割線--------------------
想了解更多,關注關注個人微信公衆號:守候書閣