vue2.0中组建里面套用组件_手把手教你撸个vue2.0弹窗组件

手把手教你撸个vue2.0弹窗组件

在开始之前需要了解一下开发vue插件的前置知识,推荐先看一下vue官网的插件介绍

搭建项目

vue-cli将你的vue项目初始化建好 vue init webpack my-project

平常我们引入插件的流程是:

npm i -S

import Vue from 'vue'

import xxx from 'xxx'

Vue.use(xxx)

所以可以在node_modules下面新建一个你的开发目录,我这里命名为kiko,

所以现在大概引入我们的开发插件的步骤为(项目最终构建完会采取发布npm包的形式)

import Vue from 'vue'

import Kiko from '../node_modules/kiko/index.js'

Vue.use(Kiko)

在你的项目目录下通过npm init指令来初始化一个package.json文件,默认指定你的入口文件index.js,并在你的项目根目录下新建一个index.js入口文件

这里会构建4中类型的弹窗组件(message、toolTip、confirm、loading),基本的结构如图所示

入口文件(可以先略过)

Vue.js 的插件应当有一个公开方法 install 。这个方法的第一个参数是 Vue 构造器 , 第二个参数是一个可选的选项对象;通过全局方法 Vue.use() 使用插件;可以再次看下vue官网的插件介绍

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

在项目的根目录创建message组件,通过

Vue.prototype.$kiko_message = function (methodOptions) {

// 逻辑...

}

来添加实例方法全局以调用this.$kiko_message()的方式来调用message

message组件结构

main.vue

{{message}}

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);

}

}

}

index.js

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上。

toolTip

没有选择通过固化在页面中的方式来引入toolTip,因为考虑到可能在页面中的任何地方引入toolTip,如果固化了,将会大大限制toolTip的使用场景。所以采用了一个绑定到Vue.prototype的this.$kiko_tooltip全局方法来触发,这样就可以自定义触发方式,只需要通过传入$event就可以自动地定位任何有需要的元素了。

toolTip组件结构

同message组件结构

main.vue

{{content}}

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)

}

}

}

.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);

}

index.js

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

confirm在保留页面的情况下会弹出一个对话框,适合一些场景更大的情况。可以用来进行一些复杂带校验的弹窗信息展示,也可以只用于简单信息的展示。可以通过title属性来显示任意标题,通过width属性来修改显示区域的宽度。

confirm组件结构

同message组件

main.vue

{{title}}

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)

}

}

}

index.js

import Vue from 'vue'

import Confirm from './src/main.vue'

export default Confirm

这里通过组件的方式进行引入,可以只是简单地信息提示,也可以自己进行一些复杂的校验。对组件的显示与隐藏这里引用了.sync修饰符,也可以通过v-if指令。运用slot来分发内容。

loading

考虑到可能不需要整屏渲染,只需要局部加载loading,在指定的位置可以按需通过自定义指令来实现,通过Element.getBoundingClientRect()方法根据需要的元素位置、区域大小自动定位;若想整屏渲染,则需要加个.fullscreen修饰符。

loading组件结构

同message组件

main.vue

export default {

name: 'kiko-loading',

data () {

return {

top: 0,

left: 0,

width: '100%',

height: '100%'

}

}

}

index.js

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 发包

确保你的项目的根目录的package.json文件已经建好

在你的项目目录下登录npm login(之后按提示填写信息)

发包npm publish

如果执行npm publish出现错误,可能是你的包名已经被注册过,在npm 官网上搜索一下是否已被注册了。若发包成功,你就可以在npm官网上搜索到自己的包。

发包成功后,就可以通过

`

import Vue from 'vue'

// 我的npm包是kiko-rascalhao

import Kiko from 'kiko-rascalhao'

Vue.use(Kiko)

`

引入你的插件啦

由于本人学识有限,有很多需要提升的地方,望大家多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值