应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

uni-app弹窗,小程序,弹出层。自定义组件弹窗,解决滚动穿透

7837人阅读 2021/6/25 10:14 总访问:5182901 评论:0 收藏:0 手机
分类: 移动开发

官方文档:https://uniapp.dcloud.net.cn/component/uniui/uni-popup.html

最简单的弹出一句话:

需要什么东西在内容里边加就行了

  1. <template>
  2. <view>
  3. <uni-popup ref="popup" background-color="#fff" >
  4. 士大夫大师傅
  5. </uni-popup>
  6. <button type="default" @click="openView()">点击</button>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. }
  14. },
  15. methods: {
  16. openView()
  17. {
  18. this.$refs.popup.open();
  19. }
  20. }
  21. }
  22. </script>
  23. <style>
  24. </style>

弹出中加两个按钮:

  1. <template>
  2. <view>
  3. <uni-popup ref="popup" background-color="#fff" >
  4. <view class="popup-content" :class="{ 'popup-height': type === 'left' || type === 'right' }">
  5. <button class="button popup-success" @click="toAddNoteHtml()"><text
  6. class="button-text success-text">html编辑器(app上推荐使用)</text></button>
  7. <button style="margin-top: 10px;" class="button popup-error" @click="toAddNoteMarkdown()"><text
  8. class="button-text error-text">markdown编辑器(临时简版)</text></button>
  9. </view>
  10. </uni-popup>
  11. <button type="default" @click="openView()">点击</button>
  12. </view>
  13. </template>
  14. <script>
  15. export default {
  16. data() {
  17. return {
  18. }
  19. },
  20. methods: {
  21. openView()
  22. {
  23. this.$refs.popup.open();
  24. }
  25. }
  26. }
  27. </script>
  28. <style>
  29. </style>

弹出中添加表单元素:

  1. <template>
  2. <view style="width: 100%;">
  3. <uni-popup ref="popup" style="width: 100%;" background-color="#fff">
  4. <view class="popupView">
  5. <!-- 基础表单校验 -->
  6. <uni-forms ref="valiForm" :rules="rules" :modelValue="valiFormData" label-position="top">
  7. <uni-forms-item label="标题" style="margin-top: -8px;" required name="name">
  8. <uni-easyinput v-model="valiFormData.name" placeholder="请输入标题" />
  9. </uni-forms-item>
  10. <uni-forms-item label="类型" style="margin-top: -8px;" required name="type">
  11. <uni-data-picker :localdata="items" :clearable="false"></uni-data-picker>
  12. </uni-forms-item>
  13. </uni-forms>
  14. <button type="primary" @click="submit('valiForm')">提交</button>
  15. </view>
  16. </uni-popup>
  17. <button type="default" @click="openView()">点击</button>
  18. </view>
  19. </template>
  20. <script>
  21. export default {
  22. data() {
  23. return {
  24. items: [{
  25. text: "一年级",
  26. value: "1-0",
  27. children: [{
  28. text: "1.1班",
  29. value: "1-1"
  30. },
  31. {
  32. text: "1.2班",
  33. value: "1-2"
  34. }
  35. ]
  36. },
  37. {
  38. text: "二年级",
  39. value: "2-0"
  40. },
  41. {
  42. text: "三年级",
  43. value: "3-0"
  44. }
  45. ],
  46. // 校验表单数据
  47. valiFormData: {
  48. name: '',
  49. type: '',
  50. },
  51. // 校验规则
  52. rules: {
  53. name: {
  54. rules: [{
  55. required: true,
  56. errorMessage: '笔记标题不能为空'
  57. }]
  58. },
  59. type: {
  60. rules: [{
  61. required: true,
  62. errorMessage: '类型不能为空'
  63. }]
  64. }
  65. }
  66. }
  67. },
  68. methods: {
  69. openView() {
  70. this.$refs.popup.open();
  71. },
  72. submit(ref) {
  73. this.$refs[ref].validate().then(res => {
  74. uni.showToast({
  75. title: "功能开发中...",
  76. icon: "none"
  77. })
  78. console.log(res);
  79. }).catch(err => {
  80. console.log('err', err);
  81. })
  82. }
  83. }
  84. }
  85. </script>
  86. <style scoped>
  87. /deep/.uni-popup .uni-popup__wrapper {
  88. width: 80% !important;
  89. padding: 40rpx;
  90. }
  91. /* .popupView {
  92. width: 600rpx;
  93. padding: 40rpx;
  94. } */
  95. </style>

在vue3中的使用

基本使用

页面上也是一样

  1. <uni-popup ref="classRankingPopup" type="bottom">班级排名</uni-popup>

打开弹窗的地方这么写:

  1. // 这里的名称保持和uni-popup上面的ref名称一致即可
  2. let classRankingPopup =ref()
  3. const openClassRankingPopup = ()=>{
  4. classRankingPopup.value.open()
  5. }

弹窗里边加入一个组件

实现的效果:

组件的代码,圆角这些也是写到这个组件里边,相当于就是弹窗里边的内容,取名叫classSort

  1. <template>
  2. <view class="container">
  3. <scroll-view scroll-y="true" style=" height: 1099rpx;">
  4. <view class="titleWrap">
  5. <view class="title">班级排名</view>
  6. <view>×</view>
  7. </view>
  8. <view class="splitline"></view>
  9. <view class="sortWrap">
  10. <view class="sortItem" :class="index>2?'simpleIndex':''" v-for="(item, index) in 9" v-bind:key="index">
  11. <!-- 前三名使用图标展示 -->
  12. <view class="sortUserWrap" v-if="index<=2">
  13. <image class="sort_img" :src="'../../static/sort_'+(index+1)+'.png'">
  14. </image>
  15. <view class="userName">李美丽</view>
  16. </view>
  17. <view class="sortUserWrap" v-else>
  18. <view class="sortIndex">{{(index+1)}}</view>
  19. <view class="userName">李美丽{{(index+3)}}</view>
  20. </view>
  21. <view class="sortCompleteWrap">
  22. <view class="scoreItem">健康:6</view>
  23. <view class="scoreItem">思维:6</view>
  24. <view class="scoreItem">技术:6</view>
  25. <view class="scoreItem">管理:6</view>
  26. <view class="scoreItem">总分:6</view>
  27. </view>
  28. </view>
  29. </view>
  30. </scroll-view>
  31. </view>
  32. </template>
  33. <script setup lang="ts">
  34. import { ref, reactive } from 'vue'
  35. </script>
  36. <style lang="scss" scoped>
  37. .container {
  38. height: 1099rpx;
  39. background-color: #fff;
  40. // border-radius: 10px;
  41. border-top-left-radius: 20rpx;
  42. border-top-right-radius: 20rpx;
  43. padding-left: 20rpx;
  44. padding-right: 20rpx;
  45. .sortWrap {
  46. margin-top: 39rpx;
  47. }
  48. .sortItem {
  49. display: flex;
  50. align-items: center;
  51. margin-top: 30rpx;
  52. .sortUserWrap {
  53. display: flex;
  54. align-items: center;
  55. width: 200rpx;
  56. // background-color: #ffabcd;
  57. //宽高比 0.765957
  58. .sort_img{
  59. width: 50rpx;
  60. height: 65.27rpx;
  61. }
  62. .sortIndex {
  63. background: #CFE4FF;
  64. color: #4E84FD;
  65. width: 50rpx;
  66. height: 50rpx;
  67. border-radius: 50%;
  68. text-align: center;
  69. line-height: 50rpx;
  70. }
  71. .userName {
  72. font-size: 31rpx;
  73. margin-left: 10rpx;
  74. color: #174A90;
  75. }
  76. }
  77. }
  78. .simpleIndex{
  79. margin-top: 39rpx;
  80. }
  81. .sortCompleteWrap {
  82. display: flex;
  83. margin-left: 15rpx;
  84. color: #565A67;
  85. font-size: 30rpx;
  86. // background: #abcdff;
  87. justify-content: space-between;
  88. flex: 1;
  89. // .scoreItem {
  90. // margin-left: 7rpx;
  91. // }
  92. }
  93. }
  94. .titleWrap {
  95. display: flex;
  96. padding-top: 22rpx;
  97. justify-content: space-between;
  98. padding-left: 20rpx;
  99. padding-right: 20rpx;
  100. .title {
  101. color: #3A3B42;
  102. }
  103. }
  104. .splitline {
  105. // border: 1rpx solid #E6E6E6;
  106. margin-left: -20rpx;
  107. margin-right: -20rpx;
  108. margin-top: 30rpx;
  109. height: 1rpx;
  110. background: #f3f3f3;
  111. }
  112. </style>

页面上的地方

  1. <uni-popup ref="classRankingPopup" type="bottom">
  2. <classSort></classSort>
  3. </uni-popup>

js:

  1. <script lang="ts" setup>
  2. import classSort from '@/pages/home/classSort.vue'
  3. let classRankingPopup = ref()
  4. const openClassRankingPopup = () => {
  5. classRankingPopup.value.open()
  6. }
  7. </script>


在微信小程序中自定义组件时,编译可能会报Component is not found in path ‘…’。可以尝试关闭后重新编译一下,或者修改一下组件的目录级别试试,比如加一个component文件夹。

组件里边实现弹窗的关闭

由于弹窗的关闭按钮我们写到了组件里边,所以需要在组件里边来触发父组件的方法,定义一个事件在子组件里边调用一下方法即可。

子组件

给叉叉加一个点击事件:

  1. <view class="titleWrap">
  2. <view class="title">班级排名</view>
  3. <view @click="handleClose">×</view>
  4. </view>

点击事件里边去调用父组件传递过来的方法:

  1. <script setup lang="ts" name="classSort">
  2. import { ref, reactive } from 'vue'
  3. // 触发closePopup事件
  4. const emit = defineEmits(['closePopup'])
  5. const handleClose = () => {
  6. emit('closePopup', '参数')
  7. }
  8. </script>
父组件

绑定一下closePopup事件:

  1. <uni-popup ref="classStarMorePopup" type="bottom" @change="change">
  2. <classStarMore @closePopup="closeClassStarMorePopup" />
  3. </uni-popup>

在事件里边去关闭弹窗即可:

  1. const closeClassStarMorePopup = () => {
  2. classStarMorePopup.value.close()
  3. }

解决滚动穿透


防止在弹窗里边滚动的时候主页面也跟着滚动了。

在引入弹窗的页面加入如下的代码:
加到最上面的位置

  1. <template>
  2. <!-- 解决滚动穿透 -->
  3. <page-meta :page-style="'overflow:' + (state.popupShow ? 'hidden' : 'visible')"></page-meta>

然后需要有一个state.popupShow属性

  1. const state = reactive({
  2. popupShow: false,
  3. title: '更新',
  4. })

然后在弹窗里边加一个change事件
用于监听弹窗是否被打开,打开的时候就要禁用当前页面的滚动了撒。如果有多个弹窗可以监听一个事件即可。

  1. <uni-popup ref="classStarMorePopup" type="bottom" @change="change">
  2. <classStarMore @closePopup="closeclassStarMorePopup" />
  3. </uni-popup>
  4. <uni-popup ref="scoreRecordPopup" type="bottom" @change="change">
  5. <scoreRecord @closePopup="closescoreRecordPopup" />
  6. </uni-popup>

change事件就是修改一下state.popupShow属性的状态

  1. const change = (e: any) => {
  2. state.popupShow = e.show
  3. }

弹窗样式效果2,带一点tag菜单的效果

效果图:

代码:
  1. <template>
  2. <view class="classStarMore_container">
  3. <scroll-view scroll-y="true" style=" height: 999rpx;">
  4. <view class="titleWrap">
  5. <view class="title">班级之星</view>
  6. <view @click="handleClose">×</view>
  7. </view>
  8. <view class="classStar">
  9. <view class="splitline"></view>
  10. <view class="tagWrap">
  11. <view class="tagContent">
  12. <view class="tagItem" :class="dealClassStarChoise(1)" @tap="getStuScoreSortByClassAndType(1)">
  13. 健康
  14. </view>
  15. <view class="tagItem" :class="dealClassStarChoise(2)" @tap="getStuScoreSortByClassAndType(2)">
  16. 思维
  17. </view>
  18. <view class="tagItem" :class="dealClassStarChoise(3)" @tap="getStuScoreSortByClassAndType(3)">
  19. 技术
  20. </view>
  21. <view class="tagItem" :class="dealClassStarChoise(4)" @tap="getStuScoreSortByClassAndType(4)">
  22. 管理
  23. </view>
  24. </view>
  25. <view>
  26. <!-- <view class="moreTag">更多 ></view> -->
  27. </view>
  28. </view>
  29. <view class="sortWrap">
  30. <view class="sortItem" :class="index > 2 ? 'simpleIndex' : ''" v-for="(item, index) in 10"
  31. v-bind:key="index">
  32. <view class="sortUserWrap" v-if="index <= 3">
  33. <image class="sort_img" :src="'../../static/sort_' + index + '.png'">
  34. </image>
  35. <view class="userName">缪喵{{ index }}</view>
  36. </view>
  37. <view class="sortUserWrap" v-else>
  38. <view class="sortIndex">{{ index }}</view>
  39. <view class="userName">缪喵{{ index }}</view>
  40. </view>
  41. <view class="sortCompleteWrap">
  42. <view class="completeScoreValue">积分:{{ index * 20 }}</view>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. </scroll-view>
  48. </view>
  49. </template>
  50. <script setup lang="ts">
  51. import { ref, reactive, defineProps, inject } from 'vue'
  52. import { onShow } from '@dcloudio/uni-app'
  53. const state = reactive({
  54. studentScoreSortType: [] as any,
  55. // 这里配置默认选中的
  56. taskTypeEnum: 2
  57. })
  58. const emit = defineEmits(['closePopup'])
  59. const handleClose = () => {
  60. emit('closePopup', '参数')
  61. }
  62. onShow(() => {
  63. })
  64. const getStuScoreSortByClassAndType = async (taskTypeEnum: number) => {
  65. console.log("处理点击",taskTypeEnum)
  66. // 数据请求换成自己的逻辑
  67. state.taskTypeEnum = taskTypeEnum
  68. }
  69. // 处理样式选中
  70. const dealClassStarChoise = (taskTypeEnum: number) => {
  71. if (taskTypeEnum === state.taskTypeEnum) {
  72. return "cur"
  73. }
  74. }
  75. </script>
  76. <style lang="scss" scoped>
  77. .classStarMore_container {
  78. height: 999rpx;
  79. background-color: #fff;
  80. // border-radius: 10px;
  81. border-top-left-radius: 20rpx;
  82. border-top-right-radius: 20rpx;
  83. .titleWrap {
  84. display: flex;
  85. padding-top: 22rpx;
  86. justify-content: space-between;
  87. padding-left: 20rpx;
  88. padding-right: 20rpx;
  89. font-size: 30rpx;
  90. .title {
  91. color: #3A3B42;
  92. }
  93. }
  94. .splitline {
  95. margin-top: 20rpx;
  96. height: 1rpx;
  97. background: #E6E6E6;
  98. }
  99. .classStar {
  100. background-color: #fff;
  101. margin-top: 23rpx;
  102. // padding-top: 23rpx;
  103. padding-bottom: 23rpx;
  104. .classStarTitle {
  105. font-size: 30rpx;
  106. color: #3A3B42;
  107. margin-left: 20rpx;
  108. // margin-top: 23rpx;
  109. }
  110. .tagWrap {
  111. display: flex;
  112. justify-content: space-between;
  113. margin-top: 23rpx;
  114. .tagContent {
  115. display: flex;
  116. margin-left: 20rpx;
  117. .tagItem {
  118. width: 110rpx;
  119. height: 45rpx;
  120. line-height: 45rpx;
  121. text-align: center;
  122. margin-right: 30rpx;
  123. background: #F5F5F5;
  124. border-radius: 25px 25px 25px 25px;
  125. font-size: 28rpx;
  126. color: #909399;
  127. }
  128. .cur {
  129. background-color: #4D9DF5;
  130. color: #FFFFFF;
  131. }
  132. }
  133. .moreTag {
  134. color: #4D9DF5;
  135. font-size: 24rpx;
  136. height: 45rpx;
  137. line-height: 45rpx;
  138. margin-right: 30rpx;
  139. }
  140. }
  141. .sortItem {
  142. display: flex;
  143. align-items: center;
  144. margin-top: 30rpx;
  145. margin-left: 36rpx;
  146. margin-right: 36rpx;
  147. justify-content: space-between;
  148. .sortUserWrap {
  149. display: flex;
  150. align-items: center;
  151. //宽高比 0.765957
  152. .sort_img {
  153. // width: 43rpx;
  154. // height: 56.13rpx;
  155. width: 36rpx;
  156. height: 47.14rpx;
  157. }
  158. .sortIndex {
  159. background: #CFE4FF;
  160. color: #4E84FD;
  161. width: 36rpx;
  162. height: 36rpx;
  163. border-radius: 50%;
  164. text-align: center;
  165. line-height: 36rpx;
  166. font-size: 24rpx;
  167. }
  168. .userName {
  169. font-size: 26rpx;
  170. margin-left: 10rpx;
  171. color: #174A90;
  172. }
  173. }
  174. .completeScoreValue {
  175. color: #565A67;
  176. font-size: 24rpx;
  177. }
  178. }
  179. }
  180. }
  181. </style>

弹窗样式效果3

效果图如下:

代码如下:
  1. <template>
  2. <view class="completeUsers-container">
  3. <scroll-view scroll-y="true" style=" height: 799rpx;">
  4. <view class="titleWrap">
  5. <view class="title">完成人次</view>
  6. <view class="closeTag" @click="handleClose">×</view>
  7. </view>
  8. <view class="splitline"></view>
  9. <div class="cc-users-content" style="">
  10. <div class="item" v-for="(item,index) in 18" :key="index">缪喵喵</div>
  11. </div>
  12. </scroll-view>
  13. </view>
  14. </template>
  15. <script setup lang="ts" name="completeUsers">
  16. import { ref, reactive } from 'vue'
  17. // 触发closePopup事件
  18. const emit = defineEmits(['closePopup'])
  19. const handleClose = () => {
  20. emit('closePopup', '参数')
  21. }
  22. </script>
  23. <style lang="scss" scoped>
  24. .completeUsers-container {
  25. height: 799rpx;
  26. background-color: #fff;
  27. border-top-left-radius: 60rpx;
  28. border-top-right-radius: 60rpx;
  29. padding-left: 20rpx;
  30. padding-right: 20rpx;
  31. .cc-users-content {
  32. display: flex;
  33. justify-content: space-between;
  34. flex-wrap: wrap;
  35. margin-top: 20rpx;
  36. .item {
  37. font-family: PingFang SC, PingFang SC;
  38. font-weight: 400;
  39. font-size: 28rpx;
  40. color: #313960;
  41. background-color: #F7F8FB;
  42. border-radius: 10rpx 10rpx 10rpx 10rpx;
  43. flex: 0 0 24%;
  44. height: 60rpx;
  45. text-align: center;
  46. line-height: 60rpx;
  47. /* 边距懒得算,css函数代替 */
  48. margin-right: calc(4% / 3);
  49. margin-bottom: calc(4% / 3);
  50. }
  51. /* 去除每行尾的多余边距 */
  52. .item:nth-child(4n) {
  53. margin-right: 0;
  54. }
  55. /* 使最后一个元素的边距填满剩余空间 */
  56. .item:last-child {
  57. margin-right: auto;
  58. }
  59. }
  60. }
  61. .titleWrap {
  62. display: flex;
  63. padding-top: 22rpx;
  64. padding-left: 20rpx;
  65. padding-right: 20rpx;
  66. justify-content: center;
  67. align-items: center;
  68. /* 垂直居中 */
  69. position: relative;
  70. .title {
  71. font-family: PingFang SC, PingFang SC;
  72. font-weight: bold;
  73. font-size: 36rpx;
  74. color: #313960;
  75. }
  76. .closeTag {
  77. position: absolute;
  78. right: 10rpx;
  79. }
  80. }
  81. .splitline {
  82. // border: 1rpx solid #E6E6E6;
  83. margin-left: -20rpx;
  84. margin-right: -20rpx;
  85. margin-top: 30rpx;
  86. height: 1rpx;
  87. background: #f3f3f3;
  88. }
  89. </style>

欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

uni-app开始时间与结束时间(结束时间大于开始时间)picker编写

利用uni-app官网里面picker插件代码当点击开始时间后结束时间要大于选择后的开始时间,点击结束时间后开始时间要小于开始时...

uni-app用法与html标签的变化

以前是html标签,比如,现在是小程序组件,比如。那么标签和组件有什么区别,不都是用尖括号包围起来一段英文吗?其实标签...

uni-app无法导入插件

点击网页中右上角的插件导入,可以打开项目,但是就是无法导入插件。是因为,要登录!hbuilder里边也要登录才行,他这个应...

使用uni-app的云端一体插件

初次使用uni-app的云端一体插件步骤还是有点多,也有一些坑,在这里把使用过程记录一下。 一:先下载需要的插件在插件右上...

uni-app中list插件图标问题

如图:他使用uni-icons实现的如果只有text就不会有图标有时候贴的文档不是太完善,还是要下一个完整的插件来对比一下

uni-app发起请求

代码如下:uni.request({ url:&#39;接口地址&#39;, success:(result)=&gt;{ my.lists=result.data; } })注意你的...

uni-app官方文档

https://uniapp.dcloud.io/

uni-app运行与调试

上边有菜单,可以运行到浏览器,也可以运行到内置浏览器运行到内置浏览器的效果:

uni-app引入外部资源引入外网样式

很简单代码如下:&lt;style&gt; @import&#39;http://image.tnblog.net/amazeui.min.css&#39;; &lt;/style&gt; &lt;st...

uni-app设置起始页

很简单,在pages.json里边配置即可。

uni-app页面无法跳转问题

首先检查一下有没有在pages里边配置没有配置不行的哦或者看看你的跳转方式对不对,如果跳转的是底部菜单,但是你用的是uni....

uni-app 删除失败 setting denied access to....

删除的时候如果文件夹下面还有页面,这样直接删除文件夹是会报错的:删除失败 setting denied access to....这种情况就直接...

uni-app中引入外部js

可以使用代码如下:varscript=document.createElement(&#39;script&#39;); script.src=&quot;http://image.tnblog.net/jqu...

uni-app dom操作

比如引入外部js需要用到的dom操作:varscript=document.createElement(&#39;script&#39;); script.src=&quot;http://image....

uni-app使用web-view引入页面

代码如下:&lt;template&gt; &lt;viewclass=&quot;h5-html&quot;&gt; &lt;web-view:webview-styles=&quot;webviewStyl...

uni-app真机调试

很简单只要手机开启了usb调试,然后hbuilderx会自动获取到手机的然后运行到手机即可华为手机开启use调试:一直点击版本号进...