询问框功能组件封装

207 阅读1分钟

对询问框组件的封装....直接上代码吧

1. 封装

src/components下新建my-confirm.vue组件

代码如下(示例):

<template>
  <div class="my-confirm" :class="{ fade: fade }">
    <div class="wrapper" :class="{ fade: fade }">
      <div class="header">
        <h3>{{ title }}</h3>
        <a @click="cancelCallback" href="JavaScript:;" class="iconfont icon-close-new"></a>
      </div>
      <div class="body">
        <i class="iconfont icon-warning"></i>
        <span>{{ text }}</span>
      </div>
      <div class="footer">
        <MyButton @click="cancelCallback" size="mini" type="gray">取消</MyButton>
        <MyButton @click="submitCallback" size="mini" type="primary">确认</MyButton>
      </div>
    </div>
  </div>
</template>
<script>
import MyButton from './my-button.vue'
import { onMounted, ref } from 'vue'

export default {
  name: 'MyConfirm',
  components: { MyButton },
  props: {
    title: {
      type: String,
      default: ''
    },
    text: {
      type: String,
      default: ''
    },
    cancelCallback: {
      type: Function,
      required: true
    },
    submitCallback: {
      type: Function,
      required: true
    }
  },
  setup() {
    const fade = ref(false)
    onMounted(() => {
      setTimeout(() => {
        fade.value = true
      }, 0)
    })
    return { fade }
  }
}
</script>
<style scoped lang="less">
.my-confirm {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 8888;
  background: rgba(0, 0, 0, 0);
  &.fade {
    transition: all 0.4s;
    background: rgba(0, 0, 0, 0.5);
  }
  .wrapper {
    width: 400px;
    background: #fff;
    border-radius: 4px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -60%);
    opacity: 0;
    &.fade {
      transition: all 0.4s;
      transform: translate(-50%, -50%);
      opacity: 1;
    }
    .header,
    .footer {
      height: 50px;
      line-height: 50px;
      padding: 0 20px;
    }
    .body {
      padding: 20px 40px;
      font-size: 16px;
      .icon-warning {
        color: #cf4444;
        margin-right: 3px;
        font-size: 16px;
      }
    }
    .footer {
      text-align: right;
      .xtx-button {
        margin-left: 20px;
      }
    }
    .header {
      position: relative;
      h3 {
        font-weight: normal;
        font-size: 18px;
      }
      a {
        position: absolute;
        right: 20px;
        top: 10px;
        font-size: 20px;
        width: 20px;
        height: 20px;
        line-height: 20px;
        text-align: center;
        text-decoration: none;
        color: #999;
        &:hover {
          color: #666;
        }
      }
    }
  }
}
</style>

同级新建confirm.js文件,用于创建虚拟的DOM节点

// 封装一个方法,实现确认框提示效果
import { createVNode, render } from 'vue'
import MyConfirm from './my-confirm.vue'

// 动态创建一个DOM容器
const container = document.createElement('div')
container.setAttribute('class', 'my-confirm-container')
document.body.appendChild(container)

export default ({ title, text }) => {
  return new Promise((resolve, reject) => {
    // 如果想让then触发,需要调用resolve:点击确认按钮触发
    // 如果想让catch触发,需要调用reject:点击取消按钮触发
    // 点击确认按钮
    const submitCallback = () => {
      // 销毁确认框
      render(null, container)
      resolve()
    }
    // 点击取消按钮
    const cancelCallback = () => {
      // 销毁确认框
      render(null, container)
      reject(new Error('cancel'))
    }
    // 把组件渲染到页面中
    const vnode = createVNode(MyConfirm, { title, text, cancelCallback, submitCallback })
    // 把虚拟节点渲染DOM中
    render(vnode, container)
  })
}

同级中的index.js文件中,将其注册为全局组件,并在vue实例上扩展一个实例方法 批量注册为全局组件。

import Message from '@/components/message'
import Confirm from '@/components/confirm'
// 导入components文件夹下的所有组件,封装的全局组件必须有name值

// 批量导入需要使用一个函数 require.context(dir,deep,matching)
// 参数:1. 目录  2. 是否加载子目录  3. 加载的正则匹配
const importFn = require.context('./', true, /\.vue$/)

export default {
  install(app) {
    // 批量注册全局组件
    importFn.keys().forEach(key => {
      // 导入组件
      const component = importFn(key).default
      // 注册组件
      app.component(component.name, component)
    })

    // 扩展一个实例方法
    app.config.globalProperties.$message = Message
    app.config.globalProperties.$confirm = Confirm
  }
}

main.js中以插件的方式使用我们封装好的全局组件和实例方法

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 自己封装的组件库
import myUI from './components'

createApp(App).use(store).use(router).use(myUI).mount('#app')

2. 使用

任意.vue结尾的文件中使用,这里给大家演示一下,大家根据具体需求使用即可

代码如下(示例):

<template>
  <div class="home-container">
    <my-button type="plain" size="middle" @click="showConfirm">点击显示询问框</my-button>
  </div>
</template>

<script>
import Message from '@/components/library/message.js'
import Confirm from '@/components/library/confirm.js'
export default {
  name: 'App',
  setup() {
    const showConfirm = () => {
      Confirm({ title: '警告', text: '是否继续操作?' })
        .then(ret => {
          Message({ text: '操作成功', type: 'success' })
        })
        .catch(err => {
          // 点击取消按钮触发
          if (err === 'cancel') return
          Message({ text: '操作取消', type: 'error' })
        })
    }
    return { showConfirm }
  }
}
</script>

<style lang="less">
.home-container {
  margin: 150px auto;
  width: 240px;
  height: 100px;
}
</style>

三、效果演示

b11f059f60cb43bda7fdb845e8f2bab2_tplv-k3u1fbpfcp-zoom-crop-mark_3024_3024_3024_1702.webp