vue组件开发

本文介绍开发一个弹框组件

//组件代码
<template>
  <div class="yui-wrapper">
    <transition name="fade">
      <div class="mask" v-show="showModal"></div>
    </transition>
    <transition name="yui-dialog">
      <div class="yui-alert" v-show="showModal">
        <div class="header_title">
          <slot name="title">提示</slot>
        </div>
        <div class="content">
          <slot>测试内容</slot>
        </div>
        <div class="footer">
          <div class="footer_btn" style="border-right:1px solid #eee">
            <a href="javascript:;" class="footer_btn--cancel" @click="changeStatus('hide')">取消</a>
          </div>
          <div class="footer_btn">
            <a href="javascript:;" class="footer_btn--confirm" @click="changeStatus('confirm')">确定</a>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
export default {
  name: "alert",
  props: {
    showModal: Boolean
  },
  methods: {
    changeStatus(type) {
      this.$emit("statusChange", type);
    }
  }
};
</script>
<style lang="less" scoped>
.yui-wrapper {
  .mask {
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: block;
    background: rgba(0, 0, 0, 0.4);
    position: fixed;
    z-index: 1;
  }
  .yui-alert {
    border-radius: 3px;
    position: fixed;
    width: 80%;
    background: #fff;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    margin: auto;
    display: table;
    // transform: translateX(-50%);
    .header_title {
      padding: 10px 10px 5px;
      text-align: center;
      font-size: 18px;
    }
    .content {
      text-align: center;
      color: #999;
      padding-bottom: 20px;
      border-bottom: 1px solid #eee;
    }
    .footer {
      display: flex;
      padding: 0 6px;
      .footer_btn {
        padding: 6px;
        flex: 1;
        text-align: center;
        a {
          font-size: 18px;
          width: 100%;
          display: inline-block;
        }
        .footer_btn--confirm {
          color: blue;
        }
        .footer_btn--cancel {
          color: #999;
        }
      }
    }
  }
}
</style>

弹框样式如下
在这里插入图片描述
调用方法

<template>
  <div>
    <div class="vux-demo">
      <img class="logo" src="../assets/vux_logo.png">
      <h1> </h1>
    </div>
    <group title="cell demo">
      <cell title="VUX" value="cool" is-link></cell>
    <x-button @click.native="show">弹框</x-button>
    </group>
    <confirm :showModal="showPop" @statusChange="confirmHandle">
      <div slot='title'>标题</div>
      <div> 
        test12345
      </div>
    </confirm>
  </div>
</template>

<script>
import { Group, Cell,XButton } from 'vux'
import confirm from './confirm/index.vue'
export default {
  components: {
    Group,
    Cell,
    XButton,
    confirm
  },
  data () {
    return {
      // note: changing this line won't causes changes
      // with hot-reload because the reloaded component
      // preserves its current state and we are modifying
      // its initial state.
      msg: 'Hello World!',
      showPop:false
    }
  },
  methods:{
    show(){
      this.showPop = true
    },
    confirmHandle(action){
      this.showPop = false;
      if(action == 'confirm'){
        console.log('confirm')
      }
    }
  }
}
</script>

<style>
.vux-demo {
  text-align: center;
}
.logo {
  width: 100px;
  height: 100px
}
</style>

动画相关css

.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-active /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.yui-dialog-enter-active, .yui-dialog-leave-active {
  opacity: 1;
  transition-duration: 400ms;
  transform: scale(1)!important;
  transition-property: transform, opacity!important;
}
.yui-dialog-leave-active {
  transition-duration: 300ms;
}
.yui-dialog-enter {
  opacity: 0;
  transform: scale(1.125)!important;
}
.yui-dialog-leave-active {
  opacity: 0;
  transform: scale(0.85)!important;
}

以上便是一般组件的开发方法,在父组件通过slot插槽可自定义弹框内容。父组件通过props传递数据到子组件,子组件通过$emit触发父组件注册的事件处理程序实现父子组件通信。
另外一种比较常见的组件开发方法是以插件的形式来调用组件。如下介绍

下面对以上组件进行改造,使之可以以插件的方式调用

this.$confirm({
        title:'温馨提示',
        content:'测试信息',
        onConfirm(msg){
          console.log(msg)
        }
      })

简单方便

改造代码如下

//组件代码index.vue
<template>
  <div class="yui-wrapper">
    <transition name="fade">
      <div class="mask" v-show="showValue"></div>
    </transition>
    <transition name="yui-dialog">
      <div class="yui-alert" v-show="showValue">
        <div class="header_title">
          <slot name="title">{{title}}</slot>
        </div>
        <div class="content">
          <slot><div v-html="content"></div></slot>
        </div>
        <div class="footer">
          <div class="footer_btn" style="border-right:1px solid #eee">
            <a href="javascript:;" class="footer_btn--cancel" @click="changeStatus('hide')">取消</a>
          </div>
          <div class="footer_btn">
            <a href="javascript:;" class="footer_btn--confirm" @click="changeStatus('confirm')">确定</a>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
export default {
  name: "alert",
  props: {
    showModal: Boolean,
    content:String,
    title:{
      type:String,
      default:'提示'
    }
  },
  data(){
    return {
      showValue:false
    }
  },
  watch:{
    showModal(newVal){
      this.showValue = newVal
    }
  },
  methods: {
    changeStatus(type) {
      this.$emit("statusChange", type);
    }
  }
};
</script>
<style lang="less" scoped>
.yui-wrapper {
  .mask {
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: block;
    background: rgba(0, 0, 0, 0.4);
    position: fixed;
    z-index: 1;
  }
  .yui-alert {
    border-radius: 3px;
    position: fixed;
    width: 80%;
    background: #fff;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    margin: auto;
    display: table;
    // transform: translateX(-50%);
    .header_title {
      padding: 10px 10px 5px;
      text-align: center;
      font-size: 18px;
    }
    .content {
      text-align: center;
      color: #999;
      padding-bottom: 20px;
      border-bottom: 1px solid #eee;
    }
    .footer {
      display: flex;
      padding: 0 6px;
      .footer_btn {
        padding: 6px;
        flex: 1;
        text-align: center;
        a {
          font-size: 18px;
          width: 100%;
          display: inline-block;
        }
        .footer_btn--confirm {
          color: blue;
        }
        .footer_btn--cancel {
          color: #999;
        }
      }
    }
  }
}
</style>

//插件安装代码
import ConfirmComponent from './index.vue'

let $vm
const plugin = {
  install(vue, opt = {}){
    const Confirm = vue.extend(ConfirmComponent)
    if(!$vm){
      $vm = new Confirm({
        el: document.createElement('div'),
        title:'提示'
      })
      document.body.appendChild($vm.$el)
    }
    const confirm = {
      show(options){
        for (const key in options) {
          if (options.hasOwnProperty(key) && typeof options[key] != 'function') {
            $vm[key] = options[key]        
          }
        }
        $vm.showValue = true
        $vm.$off('statusChange')
        $vm.$on('statusChange', action => {
          $vm.showValue = false
          if(action == 'confirm'){
            options && options.onConfirm && options.onConfirm(action)
          }
        })
      },
      hide () {
        $vm.showValue = false
      }
    }
    vue.prototype.$confirm = confirm.show
  }
}

export default plugin

注册插件

import confirm from './components/confirm/index.js'
Vue.use(confirm)
//调用
       <x-button @click.native="show()">弹框</x-button>
        <x-button @click.native="show2()">弹框2</x-button>


show(){
  this.showPop = true
},
show2(){
  this.$confirm({
    title:'温馨提示',
    content:'测试信息',
    onConfirm(msg){
      console.log(msg)
    }
  })
},

在这里插入图片描述

在这里插入图片描述

两种方式调用。效果无差异,显然以插件方式调用简便很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值