vue一些小技巧(2.x)

226 阅读1分钟

一、插槽

通过element-ui弹框组件为例子

<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>这是⼀段信息</span>
<span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>

这个组件内有两部分自定义内容

默认插槽或者内容插槽:可以使一些文案或者html

1、<span>这是⼀段信息</span>
具名插槽:使用`v-slot`指令来指定该部分要渲染的插槽的名字,这样就可以将内容渲染到相应的位置了。
不带name的插槽,会有一个默认的名字`default`。如果想要更明确一些,可以将它的name设置为default2、<span v-slot="footer">
        这部分内容会展示在弹框底部
   </span>

除了以上两种情况,还有一种作用域插槽

<my-dialog>
    <div>这是弹窗内容</div>
    <template v-slot:footer="footerSlotProps">
        <div>footer</div>
        <div>{{ footerSlotProps.footerInfo.name }}</div>  //父组件中访问子元素的数据
    </template>
</my-dialog>

// my-dialog文件内容
<div>
    <div>弹窗</div>
    <slot>默认内容</slot>
    <slot name="footer" :footerInfo="footerInfo">默认footer</slot>
</div>
data() {
    return {
        footerInfo: {
            name: 'ok'
        },
    }
},

二、插件

做一个简单的全局toast例子

toast.vue文件

<template>
  <transition ref="toastEl" name="toast-fade">
    <div class="x-toast" v-if="isShow">
      <div>{{message}}</div>
    </div>
  </transition>
</template>

<script>

export default {
  name: 'x-toast',
  data () {
    return {
      message: '',
      isShow: false
    }
  },
  methods: {
    close () {
      this.isShow = false
      this.$el.addEventListener('transitioned', () => {
        this.$destroy(true)
        this.$el.remove()
      })
    }
  }
}
</script>

<style>
.toast-fade-enter-active,
.toast-fade-leave-active {
  transition: opacity 0.5s;
}

.toast-fade-enter,
.toast-fade-leave-to {
  opacity: 0;
}
.x-toast {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 99999;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 12px;
  padding: 8px 10px;
  min-width: 120px;
  min-height: 18px;
  border-radius: 13px;
  background-color: hsla(0, 0%, 0%, 0.6);
  color: #fff;
  /* opacity: 0.6; */
}
</style>

toast.js

import Vue from 'vue'
import ToastEL from './main.vue'
const ToastConstructor = Vue.extend(ToastEL)

let ToastInstance

const Toast = function (params) {
  if (document.querySelector('.x-toast')) {
    ToastInstance.close()
  }

  if (typeof params === 'string') {
    params = {
      message: params
    }
  }
  const { type = 'info', message = '', duration = 2000 } = params
  ToastInstance = new ToastConstructor({
    el: document.createElement('div'),
    data: {
      message: message,
      type: type,
      duration: 3000
    }
  })

  setTimeout(() => {
    ToastInstance.close()
  }, duration)

  document.body.appendChild(ToastInstance.$el)
  ToastInstance.vm = ToastInstance.$mount()
  ToastInstance.vm.isShow = true

  return ToastInstance.vm
}

export default {
  install: Vue => {
    Vue.prototype.$toast = Toast
  }
}
index.js

import Toast from './toast.js'

export default Toast
vue 内引用
import Toast from 'components/common/toast' // 暂时在项目内
Vue.use(Toast)

this.$toast({
    message: '我是文字消息', // 必填
    duration: 3000 // 消息显示时间,单位:毫秒,默认3000ms
})