我们使用Vue的组件,通常是使用引入,然后写在template里面的做法
<component :props>
但是很多的时候,我们其实并不喜欢这样做,而是通过服务进行组件的调用,比如loading,比如alert。如果我们每次loading我还要去写一个组件,那么肯定是很繁琐的。
比如element里面我们都可以使用
this.$loading
这种形式来显示loading
但是有的时候我们会希望使用this.service的形式来进行组件的调用,而这个组件其实并不在我们的组件库里面。这个时候我们就需要手动进行编写了。
那么我们怎么进行编写呢?
首先我们可以确定的是,每个服务实际上就是创建一个组件
这个我们是很显而易见的。
因为服务也有组件的写法,他们并不冲突。
我们进行观察可以观测到。
当我们使用this.$service这种形式的写法的时候,可以看到在body下面会新增一个子dom。也就是说,实际上,我们调用了一个服务,我们的代码做了两个事情。
- 渲染一个组件为dom
- 将这个组件append到body中
我们查看vue文档或者element的源代码,我们可以找到两个关键的函数。
一个是
m
o
u
n
t
,
一
个
是
e
x
t
e
n
d
也
就
是
说
,
我
们
通
过
e
x
t
e
n
d
或
者
n
e
w
V
u
e
生
成
一
个
V
u
e
实
例
,
然
后
使
用
mount,一个是extend 也就是说,我们通过extend或者new Vue生成一个Vue实例,然后使用
mount,一个是extend也就是说,我们通过extend或者newVue生成一个Vue实例,然后使用mount对这个实例进行渲染,最后通过append挂载到body上面,我们在最开始的时候main.js里面一段代码
new Vue({
el: '#app',
router,
store,
render: h => h(App),
})
其实就是做了这个事情
然后进行图片点击放大的编写
其实在这个时候我们应该已经可以知道应该怎么做了。
我们可以借助element的el-dialog进行封装。
下面还是直接上代码把。
分成三个部分
showBigImg.vue
<template>
<el-dialog class="base-show-big-img" :visible.sync="show" width="100%">
<img :src="imgSrc" alt>
</el-dialog>
</template>
<script>
import showBigImgService from './index.js'
export default {
name: 'base-show-big-img',
components: {
},
data () {
return {
imgSrc: '',
show: false,
}
},
watch: {
show (newV, oldV) {
if (oldV === true && newV === false) {
showBigImgService.destroy()
}
}
},
methods: {
showBigImg (imgSrc) {
this.show = true
this.imgSrc = imgSrc
}
}
}
</script>
<style scoped lang='stylus'>
</style>
index.js
import ShowBigImg from './showBigImg';
let showBigImgBoxInstance;
function getShowBigImgInstance() {
showBigImgBoxInstance = showBigImgBoxInstance || ShowBigImg.newInstance();
return showBigImgBoxInstance;
}
export default {
show(imgSrc) {
return getShowBigImgInstance().show(imgSrc)
},
destroy() {
showBigImgBoxInstance = null
document.body.removeChild(document.getElementsByClassName('base-show-big-img')[0])
}
}
showBigImg.js
import ShowBigImg from './base-show-big-img.vue'
import Vue from 'vue'
ShowBigImg.newInstance= properties => {
const props=properties || {}
const Instance = new Vue({
data:props,
render(h){
return h(ShowBigImg,{
props:props
})
}
})
const component = Instance.$mount();
document.body.appendChild(component.$el);
const showBigImgInstance = Instance.$children[0];
return {
show (imgSrc) {
showBigImgInstance.showBigImg(imgSrc);
},
}
}
export default ShowBigImg
在main.js里面设置
import showBigImg from '../src/components/showBigImg'
Vue.prototype.$showBigImg = showBigImg
这样我们就可以很方便的使用了。
这里有几点我们要注意
1、单例模式
2、注意销毁
同时,这段代码还可以进行更加的优化。也就是做成指令的形式
import Vue from 'vue'
import showBigImg from '../components/showBigImg'
Vue.directive('show-big-img', {
bind: function (el) {
el.onclick = (e) => {
if (e.target.className.indexOf('test')) {
showBigImg.show('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRY0r52lXrYsov1v2ZWkc7sYh_5_AphihILeM_Pl20vbDvsKtam')
}
}
}
})
注意show里面的数据是又e来决定的,请自行替换成自己的
e.target.src