操作反馈类组件(Modal,Toast,ActionSheet)小结

Modal,Toast,ActionSheet这三个组件的写法思路几乎完全相同,这里以ActionSheet为例做一个小结。 ​

  • ActionSheet子组件的vue文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<div style="bottom: 0px; position: fixed;width: 100%;">
    <transition name="fade" >
      <div v-if="visible" style="z-index: 100;position: relative;">
        <div :class="`${prefixCls}`" v-if="!isShare">
          <h3 :class="`${prefixCls}-title`" v-if="title !== undefined"></h3>
          <div :class="`${prefixCls}-message`" v-if="message !== undefined"></div>
          <div :class="`${prefixCls}-button-list`">
            <div :class="wrapCls(index)"
                    class="um-active"
                    :key=index
                    v-for="(item, index) in btnGroup"
                    @click="btnClick(item)">
              <Feedback :activeClassName="`${prefixCls}-button-list-active`">
                <span v-if="cancelButtonIndex === index"
                    :class="`${prefixCls}-button-list-item-cancel-button-mask`">
                </span>
                  
              </Feedback>
            </div>
            
          </div>
        </div>

        <div :class="`${prefixClsShare}`"  v-if="isShare">
          <div :class="`${prefixClsShare}-message`"></div>
          <div :class="`${prefixClsShare}-list`" :key=rowIndex v-if="multipleLine" v-for="(row, rowIndex) in iconGroup">
            <div :class="`${prefixClsShare}-list-item`" :key=colIndex v-for="(col, colIndex) in row"
                 @click="iconClick(rowIndex, colIndex)">
              <div :class="`${prefixClsShare}-list-item-icon`">
                <img :src="col.icon" style="width: 36px; height: 36px"/>
              </div>
              <div :class="`${prefixClsShare}-list-item-title`"></div>
            </div>
          </div>

          <div :class="`${prefixClsShare}-list`" v-if="!multipleLine">
            <div :class="`${prefixClsShare}-list-item`" :key=index v-for="(item, index) in iconGroup">
              <div :class="`${prefixClsShare}-list-item-icon`" @click="iconClick(item)">
                <img :src="item.icon" style="width: 36px; height: 36px"/>
              </div>
              <div :class="`${prefixClsShare}-list-item-title`"></div>
            </div>
          </div>
          <Feedback :onMouseUp="cancelClick" :activeClassName="`${prefixClsShare}-cancel-button-active`">
            <div :class="`${prefixClsShare}-cancel-button`"></div>
          </Feedback>
        </div>
      </div>
    </transition>
    <div :class="`${prefixCls}-mask`" v-if='visible' @click="maskClick"></div>
  </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
export default {
	name: 'ActionSheetVue',
	data () {
  		return {
    		visible: '',
    		title: '',
    		message: '',
    		callback: '',
    		isShare: false,
    		btnGroup: '',
    		iconGroup: '',
    		multipleLine: '',
    		maskClosable: true,
    		cancelButtonText: '取消',
    		cancelButtonIndex: '',
    		destructiveButtonIndex: ''
  		}
	},
methods: {
  	cancelClick () {
    	this.visible = false
  	},
  	maskClick () {
    	if (this.maskClosable) {
      		this.visible = false
    	}
  	},
  	iconClick (rowIndex, colIndex) {
    	console.log(rowIndex, colIndex)
    	if (this.callback && typeof this.callback === 'function') {
      		const promise = this.callback(rowIndex, colIndex)
      		promise.then(() =&gt; {
        	this.visible = false
      	})
    	} else {
      		this.visible = false
    	}
  	},
  	btnClick (item) {
    	if (this.callback && typeof this.callback === 'function') {
      		const promise = this.callback(item)
      		promise.then(() =&gt; {
        	this.visible = false
      	})
    	} else {
      		this.visible = false
    	}
  	},
  	wrapCls (index) {
    	return [
      		'um-action-sheet-button-list-item',
      	{
        	[`um-action-sheet-button-list-item-destructive-button`]:this.destructiveButtonIndex === index,
        [`um-action-sheet-button-list-item-cancel-button`]: this.cancelButtonIndex === index
      }
    ]
  }
}
  • ActionSheet.js文件中定义ActionSheet的不同方法
  • 不同的方法对应的就是ActionSheet的不同类型
  • 不同的方法分别对子组件data中的属性进行不同的定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let ActionSheet = function (options) {
  if (!instance) {
		initInstance()
  	}
	ShowActionSheet(options)
}

ActionSheet.share = function (options) {

  if (!instance) {
initInstance()
  }

  instance.isShare = true

  if (options.iconGroup) {
instance.multipleLine = Array.isArray(options.iconGroup[0])
  }

  ShowActionSheet(options)

}

  • 将父组件传来的options的数据赋给instance,appendChild
let ShowActionSheet = function (options) {
  for (let prop in options) {
    if (options.hasOwnProperty(prop)) {
      instance[prop] = options[prop]
    }
  }
  document.body.appendChild(instance.$el)
  Vue.nextTick(() => {
    instance.visible = true
  })
}

完整js文件

import Vue from 'vue'
import ActionSheetVue from './ActionSheet.vue'

const ActionSheetVueConstructor = Vue.extend(ActionSheetVue)

let instance
let initInstance = function () {
  instance = new ActionSheetVueConstructor({
    el: document.createElement('div')
  })
}

let ActionSheet = function (options) {
  if (!instance) {
    initInstance()
  }
  ShowActionSheet(options)
}

ActionSheet.share = function (options) {
  if (!instance) {
    initInstance()
  }
  instance.isShare = true
  if (options.iconGroup) {
    instance.multipleLine = Array.isArray(options.iconGroup[0])
  }
  ShowActionSheet(options)
}

let ShowActionSheet = function (options) {
  for (let prop in options) {
    if (options.hasOwnProperty(prop)) {
      instance[prop] = options[prop]
    }
  }
  document.body.appendChild(instance.$el)
  Vue.nextTick(() => {
    instance.visible = true
  })
}

export default ActionSheet

  • 父组件中的调用
  <div>
    <WingBlank>
      <h3>Baisc</h3>
      <Button @click.native="showActionSheet">ShowActionSheet</Button>
      <WhiteSpace></WhiteSpace>
      <Button @click.native="shareActionSheet">ShareActionSheet</Button>
      <WhiteSpace></WhiteSpace>
      <Button @click.native="shareActionSheetMulpitleLine">ShareActionSheetMulpitleLine</Button>
    </WingBlank>
  </div>
<script>
  import WingBlank from '@/components/WingBlank'
  import Button from '@/components/Button'
  import WhiteSpace from '@/components/WhiteSpace'
  import ActionSheet from '@/components/ActionSheet'
  import Toast from '@/components/Toast'

  export default{
    components: {
      WingBlank,
      ActionSheet,
      Button,
      WhiteSpace,
      Toast
    },
    data () {
      return {}
    },
    methods: {
      showActionSheet () {
        ActionSheet({
//          title: '提示',
          message: 'I am description, description, description',
          cancelButtonIndex: 4,
          destructiveButtonIndex: 3,
          btnGroup: [
            {text: 'Operation1'},
            {text: 'Operation2'},
            {text: 'Operation3'},
            {text: 'Delete'},
            {text: 'Cancel'}
          ],
          callback: (item) => new Promise((resolve) => {
            console.log(item)
            resolve()
          })
        })
      },
      shareActionSheet () {
        ActionSheet.share({
          message: 'I am description, description, description',
          cancelButtonText: '取消',
          iconGroup: [
            {title: '发送给朋友', icon: 'https://gw.alipayobjects.com/zos/rmsportal/OpHiXAcYzmPQHcdlLFrc.png'},
            {title: '新浪微博', icon: 'https://gw.alipayobjects.com/zos/rmsportal/wvEzCMiDZjthhAOcwTOu.png'},
            {title: '生活圈', icon: 'https://gw.alipayobjects.com/zos/rmsportal/cTTayShKtEIdQVEMuiWt.png'},
            {title: '微信好友', icon: 'https://gw.alipayobjects.com/zos/rmsportal/umnHwvEgSyQtXlZjNJTt.png'},
            {title: 'QQ', icon: 'https://gw.alipayobjects.com/zos/rmsportal/SxpunpETIwdxNjcJamwB.png'}
          ],
          callback: (inputValue) => new Promise((resolve) => {
            Toast({
              message: 'closed after 1000s',
              duration: 1000
            })
            setTimeout(() => {
              console.log(inputValue)
              resolve()
            }, 1000)
          })
        })
      },
      shareActionSheetMulpitleLine () {
        ActionSheet.share({
          message: 'I am description, description, description',
          cancelButtonText: '取消',
          iconGroup: [[
            {title: '发送给朋友', icon: 'https://gw.alipayobjects.com/zos/rmsportal/OpHiXAcYzmPQHcdlLFrc.png'},
            {title: '新浪微博', icon: 'https://gw.alipayobjects.com/zos/rmsportal/wvEzCMiDZjthhAOcwTOu.png'},
            {title: '生活圈', icon: 'https://gw.alipayobjects.com/zos/rmsportal/cTTayShKtEIdQVEMuiWt.png'},
            {title: '微信好友', icon: 'https://gw.alipayobjects.com/zos/rmsportal/umnHwvEgSyQtXlZjNJTt.png'},
            {title: 'QQ', icon: 'https://gw.alipayobjects.com/zos/rmsportal/SxpunpETIwdxNjcJamwB.png'}
          ], [
            {title: '微信好友', icon: 'https://gw.alipayobjects.com/zos/rmsportal/umnHwvEgSyQtXlZjNJTt.png'},
            {title: 'QQ', icon: 'https://gw.alipayobjects.com/zos/rmsportal/SxpunpETIwdxNjcJamwB.png'}
          ]],
          callback: (row, col) => new Promise((resolve) => {
            console.log(row, col)
            resolve()
          })
        })
      }
    }
  }
</script>