做者 混元霹雳手-ziksangjavascript
接下来仍是按着咱们约定的来html
2.代码运行vue-cli 2.1版本前端
3.组件代码都在components文件夹里vue
4.主代码逻辑都在 App.vue文件夹里java
我什么都不要我只要jquery
赞git
学以前我给你们补几个知识点,用菊花想也知道若是咱们用toast组件确定是插入一个toast节点,那咱们本来用jquery如何实现,那就是定义好一个基本的toast dom节构,而后插入到根节点里,那其实vue-toast也是这么实现的es6
学以前咱们先补两个知识点。这个两个知识点学会了你就学会了,先看一个官方给的一个例子,我也是看这个东西才明白一些东西的vue-cli
使用基础 Vue 构造器,建立一个“子类”。参数是一个包含组件选项的对象。
data 选项是特例,须要注意 - 在 Vue.extend() 中它必须是函数
<div id="mount-point"></div>
// 建立构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 建立 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
//结果以下:
<p>Walter White aka Heisenberg</p>复制代码
若是咱们想建立一个实例,就是所谓的dom结构,咱们是在vue实列上建立一个'子类',能够包含,全部的选项对象,那咱们就要那到vue.extend(),并挂到已经如今的一个dom节点上,那就是#mount-point节点微信
//在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。
// 修改数据
vm.msg = 'Hello'
// DOM 尚未更新
Vue.nextTick(function () {
// DOM 更新了
})复制代码
这个知识点,其实vue讲起来是数据驱动,本质上仍是在改变dom,可是咱们在改变数据的时候。dom会重新渲染,在dom重新渲染的时候,你想拿到你想获得的dom或者改变dom ,比方说remove dom,为了确保必定能执行正确的操做,所以vue有一个更新dom的事件队列,等到这个队列完成,你再进行dom操做
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>y</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<script>
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 640) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>复制代码
仍是跟上期的spinner组件同样,先把html的适配给作一下
components/toast/toast.vue
<template>
<transition name='fade'>
<div v-show='visible' :class='position' class='toast'>
<i>{{message}}</i>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
visible: false,
message : '',
position : ''
};
}
}
</script>
<style>
.toast {
position: fixed;
left:50%;
transform:translate(-50%,-50%) scale(1);
word-wrap:break-word;
padding:10px;
text-align: center;
z-index:9999;
font-size:.3rem;
max-width:80%;
color: #fff;
border-radius: 5px;
background: rgba(0,0,0,0.7);
overflow: hidden;
}
.toast.middle{
top:50%;
}
.toast.top{
top:10%;
}
.toast.bottom{
top:90%;
}
.fade-enter-active, .fade-leave-active {
transition: transform .5s
}
.fade-enter, .fade-leave-active {
transform:translate(-50%,-50%) scale(0);
}
</style>复制代码
咱们在toast.vue先设计一个你想要的toast组件的样子,咱们在data里声明了三个数据
一.visible 对toast的显示和隐藏
二.message 显示的文字
三.positon 咱们写在动态class里,根据不一样的数据改变不一样的位置
components/toast/toast.js
import Vue from 'vue'
const ToastConstructor = Vue.extend(require('./toast.vue'))
let removeDom = event => {
event.target.parentNode.removeChild(event.target);
};
ToastConstructor.prototype.close = function() {
this.visible = false;
this.$el.addEventListener('transitionend', removeDom);
};
const Toast = (options = {}) => {
var instance = new ToastConstructor().$mount(document.createElement('div'))
let duration = options.duration || 2500;
instance.message = typeof options === 'string' ? options : options.message
instance.position = options.position || 'middle'
document.body.appendChild(instance.$el);
instance.visible = true;
Vue.nextTick(() => {
instance.timer = setTimeout(function() {
instance.close();
}, duration);
})
return instance
}
export default Toast复制代码
首先咱们要先import vue 由于咱们Vue.extend()依赖于vueconst ToastConstructor = Vue.extend(require('./toast.vue'))
这段代码就像我前面讲的同样,咱们用vue.extend()建立toast子实列
那问题来了,咱们缺乏一个挂载点,怎么办,不要急,看后面
在Toast函数里,咱们用了es6语法(options = {}),咱们把options先用了一个默认参数,默认参数是一个对象,用来传不一样的方式,显示 不一样toast的样式var instance = new ToastConstructor().$mount(document.createElement('div'))
当咱们执行Toast()的时候,咱们确定就要开始执行Toast函数了,若是执行下去咱们一行一行看
这里咱们就用到前面我所说的,如何去把子实列挂载的问题,咱们先把这子实列new出来,而后用$mount方法去挂到咱们本身建立的dom节点上,那就解决了挂载的问题,
此时的instance就是toast组件的实列了,咱们再看看官方的一个说法,如何拿到实列上的数据,如何改变实例上的数据,二者是否同步更新
ar data = { a: 1 }
var vm = new Vue({
data: data
})
vm.a === data.a // -> true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // -> 2
// ... 反之亦然
data.a = 3
vm.a // -> 3复制代码
这个官方例子,已经很明确的告诉了咱们,经过实例改变数据,此时实例内部数据会同时改变
那OK咱们接下去看let duration = options.duration || 2500;
当咱们若是没有设置显示时长,那咱们则使用默认2500,这个时长,咱们没有必要放到data数据里,由于这个不关于toast任何显示操做
instance.message = typeof options === 'string' ? options : options.message复制代码
咱们此时要显示toast组件上提示文字的时候,咱们传数据有两种形式,第一就是直接Toast('aaaa'),那此时咱们传的参数就不是一个对象,而是一个字符串,因此咱们进行判断,当咱们参数是一个字符串则直接使用options这个参数看成message
还有一种多是传参是一个对象,Toast({message:'aaaa'})此时咱们就要用options.message了instance.position = options.position || 'middle'
这个很好理解,当咱们传对象的时候,里面有postion这个属性的时候这用传的属性,否则用默认的document.body.appendChild(instance.$el);
全部的咱们要toast所显示的参数咱们都配置好了,接下来咱们就要把这个toast整个节点给添加到body里面,那咱们会奇怪,$el是什么鬼东西,若是咱们console.log(instance.$el)你会发现,是一整个toast的dom结构,那就对了,咱们须要的就是这个东西添加到body里
而后咱们让visible = true 别人都说这个是画蛇添足,由于我要作transition动画。因此这个必需要作一个显示隐藏操做,
Vue.nextTick(() => {
instance.timer = setTimeout(function() {
instance.close();
}, duration);
})复制代码
接下来很简单,咱们等一个时间等待操做,当多少时间后咱们再进行删除这个toast组件
ToastConstructor.prototype.close = function() {
this.visible = false;
this.$el.addEventListener('transitionend', removeDom);
};复制代码
咱们仍是在子实列的原型上写了一个close方法,能够拿到实列上的属性,咱们对$el进行transitionend
动画结束监听,当动画结束时的,咱们才进行删除节点,调用的是removeDom方法
最后return instance,能够对实列再进行操做
最后咱们在App.vue
<template>
<div>
<button @click='a'>点击1</button>
<button @click='b'>点击2</button>
</div>
</template>
<script>
import Toast from './components/zk-toast/toast.js'
export default {
methods : {
a () {
Toast('只是一个文字弹出')
},
b() {
Toast({
message : "有位置的设定和时间设定",
position: 'top',
duration : 1000
})
}
}
}
</script>
<style>
</style>复制代码
大家就能够点击查看效果了
一套啪啪啪拳已经打完收工,在这个原理上,咱们能够再去建立一个些messagebox这种组件,其实本质就上就是相似的东西,天天都在梦想而奋斗,晚安你们!
渣渣前端开发工程师,喜欢钻研,热爱分享和讲解教学, 微信 zzx1994428 QQ494755899
支持我继续创做和感到有收获的话,请向我打赏点吧
若是转载请标注出自@混元霹雳手ziksang