跨平台应用开发进阶(七) :uni-app 自定义 showToast

x33g5p2x  于2022-04-06 转载在 其他  
字(7.2k)|赞(0)|评价(0)|浏览(1197)

一、前言

利用uni-app跨平台开发框架开发多终端APP时,应用HBuilder自身提供的弹窗不满足业务需求,故开发自定义弹窗组件showToast。该组件主要实现以下功能:

  • 支持标题、内容、按钮自定义;
  • 支持根据按钮标识执行不同业务逻辑;
  • 支持内容自适应;
  • 支持弹窗关闭按钮自定义显示隐藏;

完整代码下载详参【拓展阅读】章节。

二、实现原理

应用自定义指令结合自定义组件实现视图渲染及控制逻辑,应用Vuex实现状态管理。

首先在main.js定义全局组件,并在initToast.js中注册$showToastVue原型上,以方便全局调用。

  1. // main.js
  2. import initToast from "@/components/bocft-toast/initToast.js"
  3. import showToast from "@/components/bocft-toast/bocft-toast.vue"
  4. initToast(Vue);
  5. Vue.component('show-toast',showToast);

三、代码实现

initToast.js中注册$showToastVue原型上实现逻辑如下:

  1. // initToast.js
  2. import Vuex from 'vuex'
  3. export default function initToast(v) {
  4. // 挂在store到全局Vue原型上
  5. v.prototype.$toastStore = new Vuex.Store({
  6. state: {
  7. show:false,
  8. icon:"success",//success:成功;fail:失败
  9. title:"标题",
  10. content:'内容',
  11. success:null,
  12. downLoadUrl:null,
  13. toastCloseIconShow: '',
  14. toastCloseIconStyle: '',
  15. ......
  16. },
  17. mutations: {
  18. hideToast(state) {
  19. // 小程序导航条页面控制
  20. // #ifndef H5
  21. if(state.hideTabBar){
  22. wx.showTabBar();
  23. }
  24. // #endif
  25. state.show = false;
  26. },
  27. // 按钮1方法
  28. buttonOneClick(state, data) {
  29. let _this = this;
  30. console.log('data.flag:', data.flag)
  31. switch (data.flag) {
  32. case 'hide':
  33. state.show = false;
  34. break;
  35. ......
  36. }
  37. },
  38. // 按钮2方法
  39. buttonTwoClick(state, data) {
  40. let _this = this;
  41. this.progress = 0;
  42. this.upshow = true; //切换进度条显示
  43. switch (data.flag) {
  44. case 'reload':
  45. state.show = false;
  46. break;
  47. }
  48. },
  49. close() {
  50. this.show2 = false; //关闭更新弹窗
  51. this.upshow = false; //关闭进度条
  52. uni.showTabBar(); //显示tabbar
  53. this.$emit('closeVersion');//关闭show组件
  54. },
  55. showToast(state,data) {
  56. state = Object.assign(state,data)
  57. console.log('state:', state);
  58. state.show = true
  59. // 按钮不展示时,延时2S隐藏提示框
  60. if (!state.buttonShow) {
  61. setTimeout(()=>{
  62. state.show = false
  63. return state.success(state.icon)
  64. },2000)
  65. }
  66. },
  67. success(state,data) {
  68. // state = Object.assign(state,data)
  69. // console.log(state);
  70. // state.show = true
  71. // setTimeout(()=>{
  72. // state.show = false
  73. // return state.success(state.icon)
  74. // },2000)
  75. }
  76. }
  77. })
  78. // 注册$showToast到Vue原型上,以方便全局调用
  79. v.prototype.$showToast = function (option) {
  80. if (typeof option === 'object') {
  81. // #ifndef H5
  82. if(option.hideTabBar){
  83. wx.hideTabBar();
  84. }
  85. // #endif
  86. console.log('-------------option------------', option)
  87. v.prototype.$toastStore.commit('showToast', option)
  88. }else{
  89. throw "配置项必须为对象传入的值为:"+typeof option;
  90. }
  91. }
  92. }

视图渲染逻辑如下:

  1. // toast.vue
  2. <template>
  3. <view :class="buttonShow ? 'showToast' : '_showToast'" class="prompt-box" v-show="show" @touchmove.stop.prevent="moveHandle">
  4. <!-- 弹窗关闭按钮 -->
  5. <view v-if="toastCloseIconShow" @tap='closeToast'>
  6. <image class="Toast-close-icon" :style="{top: toastCloseIconStyle.top}" src='@/static/guanbi.png'></image>
  7. </view>
  8. <view class="_shade">
  9. </view>
  10. <view class="_ToastBox">
  11. <view class="Toast-box" :style="{minHeight: toastBoxStyle.minHeight, borderRadius: toastBoxStyle.borderRadius,
  12. top: toastBoxStyle.top, background: toastBoxStyle.background}">
  13. <view style="height: 10px;"></view>
  14. <!-- 成功图片 -->
  15. <image v-if="icon=='success' && successImgSrc != ''" :style="{width: successImgClass.width, height: successImgClass.height }"
  16. class="Toast-icon" :src='successImgSrc'></image>
  17. <!-- 成功标题 -->
  18. <text v-if="icon=='success'" class="Toast-title-success" :style="{fontSize: toastTitleSuccessStyle.fontSize,
  19. fontWeight: toastTitleSuccessStyle.fontWeight, top: toastTitleSuccessStyle.top }">{{title}}</text>
  20. <!-- 失败图片 -->
  21. <image v-if="icon=='fail'" class="Toast-icon" :src='failImgSrc' :style="{width: failImgClass.width, height: failImgClass.height }"></image>
  22. <!-- 失败标题 -->
  23. <text v-if="icon=='fail'" class="Toast-title-fail" :style="{top: toastTitleFailStyle.top}">{{title}}</text>
  24. <!-- 提示内容 -->
  25. <text class="Toast-subtitle" :style="{top: toastTitleSuccessStyle.toastSubtitleTop, color: toastTitleSuccessStyle.contentFontColor,
  26. fontSize: toastTitleSuccessStyle.contentFontSize}">{{content}}</text>
  27. <!-- 按钮组 -->
  28. <view v-if="buttonShow" class="buttonShowClass" :style="{top: buttonShowStyle.top}">
  29. <!-- 按钮1 -->
  30. <view v-if="buttonOneShow" class="sendBtn"
  31. :style="{fontFamily: buttonShowStyle.fontFamily, fontSize: buttonShowStyle.fontSize,
  32. color: buttonShowStyle.color, backgroundImage: buttonShowStyle.backgroundImage,
  33. borderTop: buttonShowStyle.borderTop, width: buttonShowStyle.width,
  34. borderRadius: buttonShowStyle.borderRadius, color: buttonOneTitleStyle.color,
  35. fontWeight: buttonOneTitleStyle.fontWeight}"
  36. @tap="buttonOneClick(buttonOneClickParam)">{{buttonOneTitle}}</view>
  37. <!-- 按钮2 -->
  38. <view v-if="buttonTwoShow" class="sendBtn"
  39. :style="{fontFamily: buttonShowStyle.fontFamily, fontSize: buttonShowStyle.fontSize,
  40. color: buttonShowStyle.color, backgroundImage: buttonShowStyle.backgroundImage,
  41. borderTop: buttonShowStyle.borderTop, width: buttonShowStyle.width, borderRadius: buttonShowStyle.borderRadius }"
  42. @tap="buttonTwoClick(buttonTwoClickParam)">{{buttonTwoTitle}}</view>
  43. </view>
  44. <view>
  45. <progress :percent="percent" stroke-width="10"></progress>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </template>
  51. <script>
  52. export default {
  53. name:"show-toast",
  54. data() {
  55. return {
  56. percent: 0,
  57. };
  58. },
  59. computed: {
  60. show(){
  61. return this.$toastStore.state.show;
  62. },
  63. title(){
  64. return this.$toastStore.state.title;
  65. },
  66. content(){
  67. return this.$toastStore.state.content;
  68. },
  69. icon(){
  70. return this.$toastStore.state.icon;
  71. },
  72. downLoadUrl(){
  73. return this.$toastStore.state.downLoadUrl;
  74. },
  75. toastCloseIconShow(){
  76. return this.$toastStore.state.toastCloseIconShow;
  77. },
  78. toastCloseIconStyle(){
  79. return this.$toastStore.state.toastCloseIconStyle;
  80. },
  81. buttonShow(){
  82. return this.$toastStore.state.buttonShow;
  83. },
  84. buttonOneShow(){
  85. return this.$toastStore.state.buttonOneShow;
  86. },
  87. buttonTwoShow(){
  88. return this.$toastStore.state.buttonTwoShow;
  89. },
  90. buttonOneTitleStyle(){
  91. return this.$toastStore.state.buttonOneTitleStyle;
  92. },
  93. toastBoxStyle(){
  94. return this.$toastStore.state.toastBoxStyle;
  95. },
  96. toastTitleSuccessStyle(){
  97. return this.$toastStore.state.toastTitleSuccessStyle;
  98. },
  99. toastTitleFailStyle(){
  100. return this.$toastStore.state.toastTitleFailStyle;
  101. },
  102. buttonShowStyle(){
  103. return this.$toastStore.state.buttonShowStyle;
  104. },
  105. buttonOneClickParam(){
  106. return this.$toastStore.state.buttonOneClickParam;
  107. },
  108. buttonTwoClickParam(){
  109. return this.$toastStore.state.buttonTwoClickParam;
  110. },
  111. successImgSrc(){
  112. return this.$toastStore.state.successImgSrc;
  113. },
  114. failImgClass(){
  115. return this.$toastStore.state.failImgClass;
  116. },
  117. successImgClass(){
  118. return this.$toastStore.state.successImgClass;
  119. },
  120. failImgSrc(){
  121. return this.$toastStore.state.failImgSrc;
  122. },
  123. buttonOneTitle(){
  124. return this.$toastStore.state.buttonOneTitle;
  125. },
  126. buttonTwoTitle(){
  127. return this.$toastStore.state.buttonTwoTitle;
  128. }
  129. },
  130. mounted() {
  131. setTimeout(()=>{
  132. this.$toastStore.commit('hideToast')
  133. this.$toastStore.commit('success',"confirm")
  134. },2000)
  135. },
  136. methods:{
  137. buttonOneClick(param){
  138. this.$toastStore.commit('buttonOneClick', {flag: param})
  139. },
  140. buttonTwoClick(param){
  141. this.$toastStore.commit('buttonTwoClick', {flag: param, url: this.downLoadUrl})
  142. },
  143. closeToast(){
  144. this.$toastStore.commit('hideToast')
  145. },
  146. clickBtn(res){
  147. this.$toastStore.commit('hideToast')
  148. this.$toastStore.commit('success',res)
  149. },
  150. moveHandle(){
  151. return;
  152. }
  153. },
  154. beforeDestroy(){
  155. this.$toastStore.commit('hideToast')
  156. },
  157. }
  158. </script>

四、拓展阅读

相关文章