預覽地址 http://haogewudi.me/kiko/inde...javascript
源碼地址 https://github.com/rascalHao/...css
日常咱們引入插件的流程是:html
npm i <package> -S import Vue from 'vue' import xxx from 'xxx' Vue.use(xxx)
因此能夠在node_modules下面新建一個你的開發目錄,我這裏命名爲kiko,
因此如今大概引入咱們的開發插件的步驟爲(項目最終構建完會採起發佈npm包的形式)vue
import Vue from 'vue' import Kiko from '../node_modules/kiko/index.js' Vue.use(Kiko)
Vue.js 的插件應當有一個公開方法 install 。這個方法的第一個參數是 Vue 構造器 , 第二個參數是一個可選的選項對象;經過全局方法 Vue.use() 使用插件;能夠再次看下vue官網的插件介紹java
import KikoMessage from './packages/message/index.js' import KikoToolTip from './packages/tips/index.js' import KikoConfirm from './packages/confirm/index.js' import KikoLoading from './packages/loading/index.js' const install = function(Vue) { Vue.component(KikoMessage.name, KikoMessage) Vue.component(KikoToolTip.name, KikoToolTip) Vue.component(KikoConfirm.name, KikoConfirm) Vue.component(KikoLoading.name, KikoLoading) Vue.prototype.$kiko_tooltip = KikoToolTip.installToolTip Vue.prototype.$kiko_message = KikoMessage.installMessage } export default install
在項目的根目錄建立message組件,經過node
Vue.prototype.$kiko_message = function (methodOptions) {webpack
// 邏輯...
}
來添加實例方法全局以調用this.$kiko_message()的方式來調用messagegit
<template> <transition name="fade"> <div class="kiko-message" v-if="isShow"> {{message}} </div> </transition> </template> <script type="text/javascript"> export default { name: 'kiko-message', data () { return { message: '', time: 3000, isShow: true } }, mounted () { this.close() }, methods: { close () { var that = this window.setTimeout(function() { that.isShow = false }, this.time); } } } </script>
import Vue from 'vue' import Message from './src/main.vue' Message.installMessage = function(options) { if (options === undefined || options === null) { options = { message: '' } } else if (typeof options === 'string' || typeof options === 'number') { options = { message: options } } var message = Vue.extend(Message) var component = new message({ data: options }).$mount() document.querySelector('body').appendChild(component.$el) } export default Message
到這裏的時候能夠看下前面的入口文件介紹,你須要經過Vue.component註冊爲組件,並把Message.installMessage方法綁定到Vue.prototype.$kiko_message上。github
沒有選擇經過固化在頁面中的方式來引入toolTip,由於考慮到可能在頁面中的任何地方引入toolTip,若是固化了,將會大大限制toolTip的使用場景。因此採用了一個綁定到Vue.prototype的this.$kiko_tooltip全局方法來觸發,這樣就能夠自定義觸發方式,只須要經過傳入$event就能夠自動地定位任何有須要的元素了。web
同message組件結構
<template> <div v-if="isShow" id="kiko_tool_tip" class="kiko-tool-tip" :class="{'left': direction === 'left', 'right': direction === 'right', 'top': direction === 'top', 'bottom': direction === 'bottom'}" :style="{'background-color': background, 'color': color, 'top': top, 'left': left}"> {{content}} <div class="arrow" :style="arrowStyleObject"></div> </div> </template> <script type="text/javascript"> export default { name: 'kikoToolTip', data () { return { isShow: true, time: 3000, content: '', direction: 'right', background: 'red', color: '#fff', arrowStyleObject: '' } }, beforeMount () { let node = document.querySelector('#kiko_tool_tip') if (node && node.parentNode) { node.parentNode.removeChild(node) } }, computed: { top () { switch (this.direction) { case 'top': return (this.rect.top - 12) + 'px' case 'bottom': return (this.rect.top + 12) + 'px' case 'left': return (this.rect.top + this.rect.height / 2) + 'px' case 'right': return (this.rect.top + this.rect.height / 2) + 'px' } }, left () { switch (this.direction) { case 'top': return (this.rect.left + this.rect.width / 2) + 'px' case 'bottom': return (this.rect.left + this.rect.width / 2) + 'px' case 'left': return (this.rect.left - 12) + 'px' case 'right': return (this.rect.left + this.rect.width + 12) + 'px' } } }, mounted () { this.initColor() this.hidden() }, methods: { initColor () { switch (this.direction.toLowerCase()) { case 'left': this.arrowStyleObject = { borderLeftColor: this.background } break; case 'right': this.arrowStyleObject = { borderRightColor: this.background } break; case 'top': this.arrowStyleObject = { borderTopColor: this.background } break; case 'bottom': this.arrowStyleObject = { borderBottomColor: this.background } break; } }, hidden () { let that = this window.setTimeout(function(){ that.isShow = false }, this.time) } } } </script> <style type="text/css"> .kiko-tool-tip { display: block; position: absolute; position: fixed; background-color: #3695CC; padding: 10px 10px; border-radius: 5px; color: #fff; white-space: nowrap; z-index: 99999999 } .kiko-tool-tip.left { transform: translate(-100%, -50%); } .kiko-tool-tip.right { transform: translate(0, -50%); } .kiko-tool-tip.top { transform: translate(-50%, -100%); } .kiko-tool-tip.bottom { transform: translate(-50%, 100%); } .kiko-tool-tip.right .arrow { display: inline-block; position: absolute; content: ''; width: 0; height: 0; top: 50%; left: -10px; border-top: 10px solid transparent; border-right: 15px solid #3695CC; border-bottom: 10px solid transparent; transform: translate(0, -50%); } .kiko-tool-tip.left .arrow { display: inline-block; position: absolute; content: ''; width: 0; height: 0; top: 50%; right: -10px; border-top: 10px solid transparent; border-left: 15px solid #3695CC; border-bottom: 10px solid transparent; transform: translate(0, -50%); } .kiko-tool-tip.top .arrow { display: inline-block; position: absolute; content: ''; width: 0; height: 0; left: 50%; bottom: -10px; border-top: 15px solid #3695CC; border-left: 10px solid transparent; border-right: 10px solid transparent; transform: translate(-50%, 0); } .kiko-tool-tip.bottom .arrow { display: inline-block; position: absolute; content: ''; width: 0; height: 0; left: 50%; top: -10px; border-bottom: 15px solid #3695CC; border-left: 10px solid transparent; border-right: 10px solid transparent; transform: translate(-50%, 0); } </style>
import Vue from 'vue' import ToolTip from './src/main.vue' ToolTip.installToolTip = function(event, opt) { var options = opt var rect = {}; ['top', 'left'].forEach(function(property) { var scroll = property === 'top' ? 'scrollTop' : 'scrollLeft' rect[property] = event.target.getBoundingClientRect()[property] + document.body[scroll] + document.documentElement[scroll] }); ['height', 'width'].forEach(function(property) { rect[property] = event.target.getBoundingClientRect()[property] }); options.rect = rect var toolTip = Vue.extend(ToolTip) var component = new toolTip({ data: options }).$mount() event.target.appendChild(component.$el) } export default ToolTip
經過Element.getBoundingClientRect()方法獲取元素的大小及其相對於視口的位置,以後對提示信息進行fixed定位。
confirm在保留頁面的狀況下會彈出一個對話框,適合一些場景更大的狀況。能夠用來進行一些複雜帶校驗的彈窗信息展現,也能夠只用於簡單信息的展現。能夠經過title屬性來顯示任意標題,經過width屬性來修改顯示區域的寬度。
同message組件
<template> <transition name="bounce"> <div class="kiko-confirm" v-if="visible"> <div class="bg"></div> <div class="kiko-container" :style="{width: width}"> <div class="header"> {{title}} <i @click="close" class="icon-remove icon-large kiko-close-btn" v-if="closeVisible"></i> </div> <div class="content"> <slot></slot> </div> <slot name="footer"> <!-- <div class="kiko-footer" slot="footer"> <a href="javscript:void(0)" class="kiko-btn make-sure">肯定</a> <a href="javscript:void(0)" class="kiko-btn cancel">取消</a> </div> --> </slot> </div> </div> </transition> </template> <script type="text/javascript"> import '../../../lib/icon/css/font-awesome.css' export default { name: 'kiko-confirm', props: { width: { type: String, default: '260px' }, title: { type: String, default: '信息' }, visible: { type: Boolean, default: false }, closeVisible: { type: Boolean, default: true } }, data () { return { } }, methods: { close () { this.$emit('update:visible', false) } } } </script>
import Vue from 'vue' import Confirm from './src/main.vue' export default Confirm
這裏經過組件的方式進行引入,能夠只是簡單地信息提示,也能夠本身進行一些複雜的校驗。對組件的顯示與隱藏這裏引用了.sync修飾符,也能夠經過v-if指令。運用slot來分發內容。
考慮到可能不須要整屏渲染,只須要局部加載loading,在指定的位置能夠按需經過自定義指令來實現,經過Element.getBoundingClientRect()方法根據須要的元素位置、區域大小自動定位;若想整屏渲染,則須要加個.fullscreen修飾符。
<template> <div class="kiko-loading" :style="{'top': top, 'left': left, 'width': width, 'height': height}"> <div class="bg"></div> <div class="kiko-container"> <i class="icon-spinner icon-spin icon-4x"></i> </div> </div> </template> <script type="text/javascript"> export default { name: 'kiko-loading', data () { return { top: 0, left: 0, width: '100%', height: '100%' } } } </script>
import Vue from 'vue' import Loading from './src/main.vue' const loadingConstructor = Vue.extend(Loading) Vue.directive('kiko-loading', { update: function(el, binding) { if (binding.oldValue != binding.value) { const options = {} options.fullScreen = binding.modifiers.fullscreen ? true : false; if (options.fullScreen) { options.top = 0 options.left = 0 options.width = '100%' options.height = '100%' } else { ['top', 'left'].forEach(function(property) { var scroll = property === 'top' ? 'scrollTop' : 'scrollLeft' options[property] = el.getBoundingClientRect()[property] + document.body[scroll] + document.documentElement[scroll] + 'px' }); ['height', 'width'].forEach(function(property) { options[property] = el.getBoundingClientRect()[property] + 'px' }); } var component = new loadingConstructor({ data: options }).$mount() var node = document.querySelector('.kiko-loading') if (node && node.parentNode) { node.parentNode.removeChild(node) } if (binding.value === true) { document.querySelector('body').appendChild(component.$el) } else { var node = document.querySelector('.kiko-loading') if (node && node.parentNode) { node.parentNode.removeChild(node) } } } } }) export default Loading
若是執行npm publish出現錯誤,多是你的包名已經被註冊過,在npm 官網上搜索一下是否已被註冊了。若發包成功,你就能夠在npm官網上搜索到本身的包。
發包成功後,就能夠經過
` import Vue from 'vue' // 個人npm包是kiko-rascalhao import Kiko from 'kiko-rascalhao' Vue.use(Kiko) ` 引入你的插件啦
因爲本人學識有限,有不少須要提高的地方,望你們多多指教。