对象:notification
目标:达成想jquery一样的代码调用方式。
方法:对象挂在到vue的prototype上,可全局应用
step1:
notification.vue————对象原型
<template>
<div>
<transition name="fade" @after-leave="afterLeave" @after-enter="afterEnter">
<div
class="notification"
:style="style"
v-show="visible"
@mouseenter="clearTimer"
@mouseleave="createTimer"
>
<span class="content">{{content}}</span>
<a class="btn" @click="handleClose">{{btn}}</a>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'Notification',
props: {
content: {
type: String,
required: true
},
btn: {
type: String,
default: "close"
}
},
data() {
return {
visible: true
}
},
computed: {
style() {
return {}
}
},
methods: {
handleClose(e) {
e.preventDefault()
this.$emit('close')
},
afterLeave() {
this.$emit('closed')
},
afterEnter() {
},
clearTimer() {
},
createTimer() {
}
}
}
</script>
<style lang="stylus" scoped>
.notification
display: inline-flex
background-color #303030
color rgba(255, 255, 255, 1)
align-items center
padding 20px
min-width 280px
box-shadow 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12)
flex-wrap wrap
transition all .3s
.content
padding 0
.btn
color #ff4081
padding-left 24px
margin-left auto
cursor pointer
</style>
复制代码
step2:
function-notification.js ——————扩展notification属性
import Notification from './notification.vue'
export default {
extends: Notification,
computed: {
style() {
return {
position: 'fixed',
right: '20px',
bottom: `${this.verticalOffset}px`
}
}
},
mounted() {
this.createTimer()
},
methods: {
createTimer() {
if (this.autoClose) {
this.timer = setTimeout(() => {
this.visible = false
}, this.autoClose)
}
},
clearTimer() {
if (this.timer) {
clearTimeout(this.timer)
}
},
afterEnter() {
//debugger
this.height = this.$el.offsetHeight
}
},
beforeDestroy() {
if (this.timer) {
clearTimeout(this.timer)
}
},
data() {
return {
verticalOffset: 0,
autoClose: 3000,
height: 0,
visible: false
}
}
}
复制代码
step3:
function.js——————对象操作
import Vue from 'vue'
import Component from './func-notification'
const NotificationConstructor = Vue.extend(Component)
const instances = []
let seed = 1
const removeInstance = (instance) => {
if (!instance) {
return
}
const len = instances.length
const index = instances.findIndex(inst => instance.id === inst.id)
instances.splice(index, 1) //delete
if (len <= 1) return
const removeHeight = instance.vm.height
for (let i = index; i < len - 1; i++) {
instances[i].verticalHeight =
parseInt(instances[i].verticalOffset) - removeHeight - 16
}
}
const notify = (options) => {
if (Vue.prototype.$isServer) return // 服务端时,不能做任何操作
const {autoClose, ...rest} = options
const instance = new NotificationConstructor({
propsData: {...rest},
data: {
autoClose: autoClose === undefined ? 3000 : autoClose
}
})
const id = `notification_${seed++}`
instance.id = id
instance.vm = instance.$mount()
document.body.appendChild(instance.vm.$el)
instance.vm.visible = true
let verticalOffset = 0
instances.forEach(item => {
verticalOffset += item.$el.offsetHeight + 16
})
verticalOffset += 16
instance.verticalOffset = verticalOffset
instances.push(instance)
instance.vm.$on('closed', () => {
removeInstance(instance)
document.body.removeChild(instance.vm.$el)
instance.vm.$destroy()
})
instance.vm.$on('close', () => {
instance.vm.visible = false
})
return instance.vm
}
export default notify
复制代码
step4:
index.js————挂在到原型上
import Notification from './notification.vue'
import Notify from './function'
export default (Vue) => {
Vue.component(Notification.name, Notification)
Vue.prototype.$notify = Notify
//加到prototype上的属性,每个组件都可以通过this.调用
}复制代码
-------------------------------show time,baby!!!------------------------
app.vue
......
<button @click="notify">click me to notify</button>
......
methods: {复制代码
notify() {
this.$notify({ //代码式的直接调用,convenient
content: '关闭提示框内容',
btn: '关闭'
})
}
},复制代码
与vue重点的组件化思想有点差别,但是种极好的一种封装思想。
重点是:非常实用~~~~(不用事先在各个界面定义好控件,随用随调,完美)。类比可封装其他的弹框等控件