Vue组件开发技巧总结


Posted in Javascript onMarch 04, 2018

前言

临近毕业,写了个简单个人博客,项目地址是点我访问项目地址(顺便求star),本篇是系列总结第一篇。接下来会一步一步模仿一个低配版的Element 的对话框和弹框组件。

正文

Vue 单文件组件开发

当使用vue-cli初始化一个项目的时候,会发现src/components文件夹下有一个HelloWorld.vue文件,这便是单文件组件的基本开发模式。

// 注册
Vue.component('my-component', {
 template: '<div>A custom component!</div>'
})

// 创建根实例
new Vue({
 el: '#example'
})

接下来,开始写一个dialog组件。

Dialog

目标对话框组件的基本样式如图:

Vue组件开发技巧总结

根据目标样式,可以总结出:

  1. dialog组件需要一个titleprops来标示弹窗标题
  2. dialog组件需要在按下确定按钮时发射出确定事件(即告诉父组件确定了)
  3. 同理,dialog组件需要发射出取消事件
  4. dialog组件需要提供一个插槽,便于自定义内容

那么,编码如下:

<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组件接收了一个nameprops,那么怎么编写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,

Vue组件开发技巧总结

接下来,我也要封装一个这样的组件。首先,整理下思路:

  1. Element的使用方法是this.$confirm,这不就是挂到Vue的prototype上就行了
  2. Element的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)

这样就有动画了。

总结

  1. 通过transition和css实现不错的动画。其中,transition组件的name决定了编写css的两个关键类名为[name]-enter-active和[name]-leave-active
  2. 通过Vue.extend继承一个组件的构造函数(不知道怎么说合适,就先这样说),然后通过这个构造函数,便可以实现组件相关属性的自定义(使用场景:js调用组件)
  3. js调用组件时,为了维持组件的动画效果可以先document.body.appendChild 然后Vue.nextTick(() => instance.visible = true)

到此,简单的Vue组件开发就总结完了,我写的相关代码在地址,https://github.com/mvpzx/elapse/tree/master/be/src/components

Javascript 相关文章推荐
基于jquery的bankInput银行卡账号格式化
Aug 22 Javascript
禁用Enter键表单自动提交实现代码
May 22 Javascript
CSS3,HTML5和jQuery搜索框集锦
Dec 02 Javascript
AngularJS中的模块详解
Jan 29 Javascript
JS实现弹性菜单效果代码
Sep 07 Javascript
Node.js开发者必须了解的4个JS要点
Feb 21 Javascript
Bootstrap基本样式学习笔记之表单(3)
Dec 07 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(2)
Feb 20 Javascript
nginx+vue.js实现前后端分离的示例代码
Feb 12 Javascript
Vue press 支持图片放大功能的实例代码
Nov 09 Javascript
Vuex持久化插件(vuex-persistedstate)解决刷新数据消失的问题
Apr 16 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
Jul 28 Javascript
代码详解javascript模块加载器
Mar 04 #Javascript
Vue用v-for给src属性赋值的方法
Mar 03 #Javascript
vue中v-for加载本地静态图片方法
Mar 03 #Javascript
基于vue中解决v-for使用报红并出现警告的问题
Mar 03 #Javascript
基于Vuejs的搜索匹配功能实现方法
Mar 03 #Javascript
vue.js select下拉框绑定和取值方法
Mar 03 #Javascript
Vuejs在v-for中,利用index来对第一项添加class的方法
Mar 03 #Javascript
You might like
php intval的测试代码发现问题
2008/07/27 PHP
神盾加密解密教程(三)PHP 神盾解密工具
2014/06/08 PHP
PHP实现通过get方式识别用户发送邮件的方法
2015/07/16 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
PHP 下载文件时如何自动添加bom头及解释BOM头和去掉bom头的方法
2016/01/04 PHP
YII中Ueditor富文本编辑器文件和图片上传的配置图文教程
2017/03/15 PHP
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
Exjs 入门篇
2010/04/07 Javascript
JSON 对象未定义错误的解决方法
2016/09/29 Javascript
js 单引号替换成双引号,双引号替换成单引号的实现方法
2017/02/16 Javascript
详解如何去除vue项目中的#——History模式
2017/10/13 Javascript
解析vue中的$mount
2017/12/21 Javascript
js判断文件类型大小并给出提示的实现方法
2018/01/03 Javascript
js实现一个简单的MVVM框架示例
2018/01/15 Javascript
使用vue.js在页面内组件监听scroll事件的方法
2018/09/11 Javascript
改进 JavaScript 和 Rust 的互操作性并深入认识 wasm-bindgen 组件
2019/07/13 Javascript
详解如何在Vue项目中发送jsonp请求
2019/10/25 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
Python中一些自然语言工具的使用的入门教程
2015/04/13 Python
通过celery异步处理一个查询任务的完整代码
2019/11/19 Python
Python 中如何实现参数化测试的方法示例
2019/12/10 Python
Pytorch 实现sobel算子的卷积操作详解
2020/01/10 Python
PageFactory设计模式基于python实现
2020/04/14 Python
自定义html标记替换html5新增元素
2008/10/17 HTML / CSS
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
会计学应届毕业生推荐信
2013/11/04 职场文书
简历的自我评价范文
2014/02/04 职场文书
会计演讲稿范文
2014/05/23 职场文书
毕业实习自我鉴定范文2014
2014/09/26 职场文书
工作检讨书怎么写
2014/10/10 职场文书
寻找最美乡村教师观后感
2015/06/18 职场文书
红色影片观后感
2015/06/18 职场文书
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
在Python 中将类对象序列化为JSON
2022/04/06 Python
彻底弄懂Python中的回调函数(callback)
2022/06/25 Python
教你win10系统中APPCRASH事件问题解决方法
2022/07/15 数码科技