如何实现一个简单的vue服务---以图片点击放大为例子

我们使用Vue的组件,通常是使用引入,然后写在template里面的做法

<component :props>

但是很多的时候,我们其实并不喜欢这样做,而是通过服务进行组件的调用,比如loading,比如alert。如果我们每次loading我还要去写一个组件,那么肯定是很繁琐的。
比如element里面我们都可以使用

this.$loading

这种形式来显示loading

但是有的时候我们会希望使用this.service的形式来进行组件的调用,而这个组件其实并不在我们的组件库里面。这个时候我们就需要手动进行编写了。

那么我们怎么进行编写呢?

首先我们可以确定的是,每个服务实际上就是创建一个组件

这个我们是很显而易见的。
因为服务也有组件的写法,他们并不冲突。
我们进行观察可以观测到。
当我们使用this.$service这种形式的写法的时候,可以看到在body下面会新增一个子dom。也就是说,实际上,我们调用了一个服务,我们的代码做了两个事情。

  1. 渲染一个组件为dom
  2. 将这个组件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,extendextendnewVueVue使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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值