临近毕业,写了个简单个人博客,项目地址是点我访问项目地址(顺便求star),本篇是系列总结第一篇。接下来会一步一步模仿一个低配版的Element 的对话框
和弹框
组件。
当使用vue-cli
初始化一个项目的时候,会发现src/components
文件夹下有一个HelloWorld.vue
文件,这便是
单文件组件的基本开发模式。
// 注册
Vue.component('my-component', {
template: 'A custom component!'
})
// 创建根实例
new Vue({
el: '#example'
})
接下来,开始写一个dialog
组件。
目标对话框组件的基本样式如图:
根据目标样式,可以总结出:
title
props来标示弹窗标题确定
按钮时发射
出确定
事件(即告诉父组件确定
了)发射
出取消
事件那么,编码如下:
<template>
<div class="ta-dialog__wrapper">
<div class="ta-dialog">
<div class="ta-dialog__header">
<span>{{ title }}span>
<i class="ios-close-empty" @click="handleCancel()">i>
div>
<div class="ta-dialog__body">
<slot>slot>
div>
<div class="ta-dialog__footer">
<button @click="handleCancel()">取消button>
<button @click="handleOk()">确定button>
div>
div>
div>
template>
<script>
export default {
name: 'Dialog',
props: {
title: {
type: String,
default: '标题'
},
},
methods: {
handleCancel() {
this.$emit('cancel')
},
handleOk() {
this.$emit('ok')
},
},
}
script>
这样便完成了dialog
组件的开发,使用方法如下:
<ta-dialog
title="弹窗标题"
@ok="handleOk"
@cancel="handleCancel">
<p>我是内容p>
ta-dialog>
这时候发现一个问题,通过使用v-if
或者v-show
来控制弹窗的展现时,没有动画!!!,看上去很生硬。教练,我想加动画
,这时候就该transition
组件上场了。使用transition
组件结合css
能做出很多效果不错的动画。接下来增强dialog
组件动画,代码如下:
<template>
<transition name="slide-down">
<div class="ta-dialog__wrapper" v-if="isShow">
// 省略
div>
transition>
template>
<script>
export default {
data() {
return {
isShow: true
}
},
methods: {
handleCancel() {
this.isShow = false
this.$emit('cancel')
},
handleOk() {
this.isShow = true
this.$emit('ok')
},
},
}
script>
可以看到transition
组件接收了一个name
props,那么怎么编写css
完成动画呢?很简单的方式,写出两个
关键class
(css 的 className)样式即可:
.slide-down-enter-active {
animation: dialog-enter ease .3s;
}
.slide-down-leave-active {
animation: dialog-leave ease .5s;
}
@keyframes dialog-enter {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes dialog-leave {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
就是这么简单就开发出了效果还不错的动效,注意transition
组件的name
为slide-down
,而编写的动画的关键className
为slide-down-enter-active
和slide-down-leave-active
。
Dialog
做MessageBox
Element的MessageBox
的使用方法如下:
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
看到这段代码,我的感觉就是好神奇好神奇好神奇(惊叹三连)。仔细看看,这个组件其实就是一个封装好的dialog
,
接下来,我也要封装一个这样的组件。首先,整理下思路:
this.$confirm
,这不就是挂到Vue
的prototype
上就行了then
是确定,catch
是取消,promise
就可以啦整理好思路,我就开始编码了:
import Vue from 'vue'
import MessgaeBox from './src/index'
const Ctur = Vue.extend(MessgaeBox)
let instance = null
const callback = action => {
if (action === 'confirm') {
if (instance.showInput) {
instance.resolve({ value: instance.inputValue, action })
} else {
instance.resolve(action)
}
} else {
instance.reject(action)
}
instance = null
}
const showMessageBox = (tip, title, opts) => new Promise((resolve, reject) => {
const propsData = { tip, title, ...opts }
instance = new Ctur({ propsData }).$mount()
instance.reject = reject
instance.resolve = resolve
instance.callback = callback
document.body.appendChild(instance.$el)
})
const confirm = (tip, title, opts) => showMessageBox(tip, title, opts)
Vue.prototype.$confirm = confirm
至此,可能会疑惑怎么callback
呢,其实我编写了一个封装好的dialog
并将其命名为MessageBox
,
它的代码中,有这样两个方法:
onCancel() {
this.visible = false
this.callback && (this.callback.call(this, 'cancel'))
},
onConfirm() {
this.visible = false
this.callback && (this.callback.call(this, 'confirm'))
},
没错,就是确定
和取消
时进行callback
。我还想说一说Vue.extend
,代码中引入了MessageBox
,
我不是直接new MessageBox
而是借助new Ctur
,因为这样可以定义数据(不仅仅是props)
,例如:
instance = new Ctur({ propsData }).$mount()
这时候,页面上其实是还没有MessageBox
的,我们需要执行:
document.body.appendChild(instance.$el)
如果你直接这样,你可能会发现MessageBox
打开的时候没有动画,而关闭的时候有动画。解决方法也很简单,
appendChild
的时候让其仍是不可见,然后使用类这样的代码:
Vue.nextTick(() => instance.visible = true)
这样就有动画了。
通过transition
和css
实现不错的动画。其中,transition
组件的name
决定了编写css
的两个关键
类名为[name]-enter-active
和[name]-leave-active
通过Vue.extend
继承一个组件的构造函数(不知道怎么说合适,就先这样说),然后通过这个构造函数,便可以
实现组件相关属性的自定义(使用场景:js调用组件)
js调用组件时,为了维持组件的动画效果可以先document.body.appendChild
然后Vue.nextTick(() => instance.visible = true)
到此,简单的Vue组件开发就总结完了,我写的相关代码在地址,欢迎指正批评,求star…