开始

可以选择9张图片 。可以对图片进行预览,同时也可以删除某一张图片。
image.png
先来看下官方提供给我们的demo例子

接口—-》媒体—-》图片
image.png
这就是我们要移植的功能。
image.png
官方的代码搜索图片
image.png

  1. {
  2. "path": "image/image",
  3. "style": {
  4. "navigationBarTitleText": "图片"
  5. }
  6. },

hello-uni-app2022\pages\API\image
image.png
复制代码
image.png

  1. <view class="uni-list list-pd">
  2. <view class="uni-list-cell cell-pd">
  3. <view class="uni-uploader">
  4. <view class="uni-uploader-head">
  5. <view class="uni-uploader-title">点击可预览选好的图片</view>
  6. <view class="uni-uploader-info">{{imageList.length}}/9</view>
  7. </view>
  8. <view class="uni-uploader-body">
  9. <view class="uni-uploader__files">
  10. <block v-for="(image,index) in imageList" :key="index">
  11. <view class="uni-uploader__file">
  12. <image class="uni-uploader__img" :src="image" :data-src="image" @tap="previewImage"></image>
  13. </view>
  14. </block>
  15. <view class="uni-uploader__input-box">
  16. <view class="uni-uploader__input" @tap="chooseImage"></view>
  17. </view>
  18. </view>
  19. </view>
  20. </view>
  21. </view>
  22. </view>

image.png

  1. var sourceType = [
  2. ['camera'],
  3. ['album'],
  4. ['camera', 'album']
  5. ]
  6. var sizeType = [
  7. ['compressed'],
  8. ['original'],
  9. ['compressed', 'original']
  10. ]

image.png

  1. imageList: [],
  2. sourceTypeIndex: 2,
  3. sourceType: ['拍照', '相册', '拍照或相册'],
  4. sizeTypeIndex: 2,
  5. sizeType: ['压缩', '原图', '压缩或原图'],
  6. countIndex: 8,
  7. count: [1, 2, 3, 4, 5, 6, 7, 8, 9]

复制chooseImage开始往下所有的方法
image.png

  1. chooseImage: async function() {
  2. // #ifdef APP-PLUS
  3. // TODO 选择相机或相册时 需要弹出actionsheet,目前无法获得是相机还是相册,在失败回调中处理
  4. if (this.sourceTypeIndex !== 2) {
  5. let status = await this.checkPermission();
  6. if (status !== 1) {
  7. return;
  8. }
  9. }
  10. // #endif
  11. if (this.imageList.length === 9) {
  12. let isContinue = await this.isFullImg();
  13. console.log("是否继续?", isContinue);
  14. if (!isContinue) {
  15. return;
  16. }
  17. }
  18. uni.chooseImage({
  19. sourceType: sourceType[this.sourceTypeIndex],
  20. sizeType: sizeType[this.sizeTypeIndex],
  21. count: this.imageList.length + this.count[this.countIndex] > 9 ? 9 - this.imageList.length : this.count[this.countIndex],
  22. success: (res) => {
  23. this.imageList = this.imageList.concat(res.tempFilePaths);
  24. },
  25. fail: (err) => {
  26. console.log("err: ",err);
  27. // #ifdef APP-PLUS
  28. if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
  29. this.checkPermission(err.code);
  30. }
  31. // #endif
  32. // #ifdef MP
  33. if(err.errMsg.indexOf('cancel') !== '-1'){
  34. return;
  35. }
  36. uni.getSetting({
  37. success: (res) => {
  38. let authStatus = false;
  39. switch (this.sourceTypeIndex) {
  40. case 0:
  41. authStatus = res.authSetting['scope.camera'];
  42. break;
  43. case 1:
  44. authStatus = res.authSetting['scope.album'];
  45. break;
  46. case 2:
  47. authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
  48. break;
  49. default:
  50. break;
  51. }
  52. if (!authStatus) {
  53. uni.showModal({
  54. title: '授权失败',
  55. content: 'Hello uni-app需要从您的相机或相册获取图片,请在设置界面打开相关权限',
  56. success: (res) => {
  57. if (res.confirm) {
  58. uni.openSetting()
  59. }
  60. }
  61. })
  62. }
  63. }
  64. })
  65. // #endif
  66. }
  67. })
  68. },
  69. isFullImg: function() {
  70. return new Promise((res) => {
  71. uni.showModal({
  72. content: "已经有9张图片了,是否清空现有图片?",
  73. success: (e) => {
  74. if (e.confirm) {
  75. this.imageList = [];
  76. res(true);
  77. } else {
  78. res(false)
  79. }
  80. },
  81. fail: () => {
  82. res(false)
  83. }
  84. })
  85. })
  86. },
  87. previewImage: function(e) {
  88. var current = e.target.dataset.src
  89. uni.previewImage({
  90. current: current,
  91. urls: this.imageList
  92. })
  93. },
  94. async checkPermission(code) {
  95. let type = code ? code - 1 : this.sourceTypeIndex;
  96. let status = permision.isIOS ? await permision.requestIOS(sourceType[type][0]) :
  97. await permision.requestAndroid(type === 0 ? 'android.permission.CAMERA' :
  98. 'android.permission.READ_EXTERNAL_STORAGE');
  99. if (status === null || status === 1) {
  100. status = 1;
  101. } else {
  102. uni.showModal({
  103. content: "没有开启权限",
  104. confirmText: "设置",
  105. success: function(res) {
  106. if (res.confirm) {
  107. permision.gotoAppSetting();
  108. }
  109. }
  110. })
  111. }
  112. return status;
  113. }

这个isFullImage方法删除。
image.png
选择到了9张图片,直接return就可以了
image.png
复制css
image.png

  1. .cell-pd {
  2. padding: 22rpx 30rpx;
  3. }
  4. .list-pd {
  5. margin-top: 50rpx;
  6. }

image.png

image.png

image.png

图片的删除功能

在image上加一个删除的图标。
image.png
选择这个垃圾桶的图标
image.png

image.png

  1. <view class="icon iconfont icon-shanchu">
  2. </view>

把图片放在图片的右上角。
image.png
首先需要选择几张图片,位置偏了
image.png
给父元素加一个相对定位。
image.png

image.png

image.png
我在本地的测试的时候,发现删除的图标被图片盖住了,所以需要加一个z-index:10 。这样才能正常的显示

  1. .icon-shanchu{
  2. position: absolute;
  3. right: 0;
  4. top: 0;
  5. background: #333333;
  6. color: #FFFFFF;
  7. padding: 2upx 10upx;
  8. z-index: 10;
  9. }

给图标加上内边距,让他好看一点,上下为2,左右为10
image.png
加个圆角
image.png

image.png

删除事件

这里的delect是故意写错的,删除应该是delete,但是delete是个关键字。这里写上后页面就会报错。
image.png

  1. @tap="delete(index)"

增加一个弹出的模态框
image.png

image.png
image.png
改成es6语法。这样才可以在里面用this对象
image.png

image.png
确定后,被删除了
image.png

本节最终代码

  1. <template>
  2. <view>
  3. <uni-nav-bar :statusBar="true" rightText="发布"
  4. left-icon="back" left-text="返回"
  5. @clickLeft="back" @clickRight="submit">
  6. <view class="u-f-ajc" @tap="changelook">
  7. {{ yinsi }}
  8. <view class="icon iconfont icon-xialazhankai"></view>
  9. </view>
  10. </uni-nav-bar>
  11. <!-- <uni-nav-bar :statusBar="true">
  12. <block slot="left">
  13. <view class="back"></view>
  14. </block>
  15. <view class="u-f-ajc" @tap="changelook">
  16. {{ yinsi }}
  17. <view class="icon iconfont icon-xialazhankai"></view>
  18. </view>
  19. <block slot="right">
  20. <view class="city">
  21. 发布
  22. </view>
  23. </block>
  24. </uni-nav-bar> -->
  25. <!-- 多行输入框 -->
  26. <view class="uni-textarea">
  27. <textarea value="" v-model="text" placeholder="说一句话吧~" />
  28. </view>
  29. <view class="uni-list list-pd">
  30. <view class="uni-list-cell cell-pd">
  31. <view class="uni-uploader">
  32. <view class="uni-uploader-head">
  33. <view class="uni-uploader-title">点击可预览选好的图片</view>
  34. <view class="uni-uploader-info">{{imageList.length}}/9</view>
  35. </view>
  36. <view class="uni-uploader-body">
  37. <view class="uni-uploader__files">
  38. <block v-for="(image,index) in imageList" :key="index">
  39. <view class="uni-uploader__file">
  40. <view class="icon iconfont icon-shanchu" @tap="delect(index)"></view>
  41. <image class="uni-uploader__img" :src="image" :data-src="image" @tap="previewImage"></image>
  42. </view>
  43. </block>
  44. <view class="uni-uploader__input-box">
  45. <view class="uni-uploader__input" @tap="chooseImage"></view>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. </view>
  53. </template>
  54. <script>
  55. let changelook = ['所有人可见', '仅自己可见'];
  56. var sourceType = [
  57. ['camera'],
  58. ['album'],
  59. ['camera', 'album']
  60. ]
  61. var sizeType = [
  62. ['compressed'],
  63. ['original'],
  64. ['compressed', 'original']
  65. ]
  66. export default {
  67. data() {
  68. return {
  69. yinsi: "所有人可见",
  70. text: "111",
  71. imageList: [],
  72. sourceTypeIndex: 2,
  73. sourceType: ['拍照', '相册', '拍照或相册'],
  74. sizeTypeIndex: 2,
  75. sizeType: ['压缩', '原图', '压缩或原图'],
  76. countIndex: 8,
  77. count: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  78. }
  79. },
  80. methods: {
  81. // 返回
  82. back(){
  83. uni.navigateBack({
  84. delta: 1
  85. })
  86. },
  87. // 发布
  88. submit(){
  89. console.log('发布')
  90. },
  91. // 隐私
  92. changelook(){
  93. console.log('隐私')
  94. uni.showActionSheet({
  95. itemList: changelook,
  96. success: function (res) {
  97. console.log(res.tapIndex);
  98. console.log(changelook[res.tapIndex]);
  99. this.yinsi=changelook[res.tapIndex];
  100. }
  101. });
  102. },
  103. chooseImage: async function() {
  104. // #ifdef APP-PLUS
  105. // TODO 选择相机或相册时 需要弹出actionsheet,目前无法获得是相机还是相册,在失败回调中处理
  106. if (this.sourceTypeIndex !== 2) {
  107. let status = await this.checkPermission();
  108. if (status !== 1) {
  109. return;
  110. }
  111. }
  112. // #endif
  113. if (this.imageList.length === 9) {
  114. // let isContinue = await this.isFullImg();
  115. // console.log("是否继续?", isContinue);
  116. // if (!isContinue) {
  117. // return;
  118. // }
  119. return;
  120. }
  121. uni.chooseImage({
  122. sourceType: sourceType[this.sourceTypeIndex],
  123. sizeType: sizeType[this.sizeTypeIndex],
  124. count: this.imageList.length + this.count[this.countIndex] > 9 ? 9 - this.imageList.length : this.count[this.countIndex],
  125. success: (res) => {
  126. this.imageList = this.imageList.concat(res.tempFilePaths);
  127. },
  128. fail: (err) => {
  129. console.log("err: ",err);
  130. // #ifdef APP-PLUS
  131. if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
  132. this.checkPermission(err.code);
  133. }
  134. // #endif
  135. // #ifdef MP
  136. if(err.errMsg.indexOf('cancel') !== '-1'){
  137. return;
  138. }
  139. uni.getSetting({
  140. success: (res) => {
  141. let authStatus = false;
  142. switch (this.sourceTypeIndex) {
  143. case 0:
  144. authStatus = res.authSetting['scope.camera'];
  145. break;
  146. case 1:
  147. authStatus = res.authSetting['scope.album'];
  148. break;
  149. case 2:
  150. authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
  151. break;
  152. default:
  153. break;
  154. }
  155. if (!authStatus) {
  156. uni.showModal({
  157. title: '授权失败',
  158. content: 'Hello uni-app需要从您的相机或相册获取图片,请在设置界面打开相关权限',
  159. success: (res) => {
  160. if (res.confirm) {
  161. uni.openSetting()
  162. }
  163. }
  164. })
  165. }
  166. }
  167. })
  168. // #endif
  169. }
  170. })
  171. },
  172. previewImage: function(e) {
  173. var current = e.target.dataset.src
  174. uni.previewImage({
  175. current: current,
  176. urls: this.imageList
  177. })
  178. },
  179. async checkPermission(code) {
  180. let type = code ? code - 1 : this.sourceTypeIndex;
  181. let status = permision.isIOS ? await permision.requestIOS(sourceType[type][0]) :
  182. await permision.requestAndroid(type === 0 ? 'android.permission.CAMERA' :
  183. 'android.permission.READ_EXTERNAL_STORAGE');
  184. if (status === null || status === 1) {
  185. status = 1;
  186. } else {
  187. uni.showModal({
  188. content: "没有开启权限",
  189. confirmText: "设置",
  190. success: function(res) {
  191. if (res.confirm) {
  192. permision.gotoAppSetting();
  193. }
  194. }
  195. })
  196. }
  197. return status;
  198. },
  199. delect(index) {
  200. uni.showModal({
  201. title:'提示',
  202. content:'是否要删除该图片',
  203. success: (res) => {
  204. if(res.confirm) {
  205. this.imageList.splice(index,1);
  206. }
  207. }
  208. })
  209. }
  210. }
  211. }
  212. </script>
  213. <style>
  214. textarea{
  215. border: 1upx solid #EEEEEE;
  216. }
  217. .cell-pd {
  218. padding: 22rpx 30rpx;
  219. }
  220. .list-pd {
  221. margin-top: 50rpx;
  222. }
  223. .uni-uploader__file{
  224. position: relative;
  225. }
  226. .icon-shanchu{
  227. position: absolute;
  228. right: 0;
  229. top: 0;
  230. background: #333333;
  231. color: #FFFFFF;
  232. padding: 2upx 10upx;
  233. z-index: 10;
  234. border-radius: 10upx;
  235. }
  236. /* .uni-navbar__header-container {
  237. justify-content: center;
  238. } */
  239. </style>

结束