微信小程序自定义地址组件

迈不过友情╰ 2022-11-15 14:12 401阅读 0赞

项目需求

  1. 需要调用后台传过来的地址,存储地址时存的是地址的id,所以市面上的地址组件均不符合我的需求,只能自定义一个。

技术选取

  1. picker-viewpicker-view-column

核心代码

region.wxml

  1. <!--地址选择器-->
  2. <view wx:if="{ {show}}" class="region-picker" catchtap="hidePicker">
  3. <view class="picker-handle" catchtap>
  4. <view class="picker-cancel" catchtap="hidePicker">取消</view>
  5. <view class="picker-confirm" catchtap="chooseRegion">确定</view>
  6. </view>
  7. <picker-view class="picker" value="{ {regions}}" bindchange="changePicker" catchtap>
  8. <picker-view-column>
  9. <view wx:for="{ {provinces}}" wx:key="code" class="region-province">{
  10. {item.name}}</view>
  11. </picker-view-column>
  12. <picker-view-column>
  13. <view wx:for="{ {citys}}" wx:key="code" class="region-city">{
  14. {item.name}}</view>
  15. </picker-view-column>
  16. <picker-view-column>
  17. <view wx:for="{ {areas}}" wx:key="code" class="region-area">{
  18. {item.name}}</view>
  19. </picker-view-column>
  20. </picker-view>
  21. </view>

region.less

  1. .region-picker {
  2. width: 100%;
  3. height: 100%;
  4. position: fixed;
  5. top: 0;
  6. left: 0;
  7. z-index: 2;
  8. background: rgba(0, 0, 0, 0.6); .picker-handle {
  9. width: 100%;
  10. height: 72rpx;
  11. display: flex;
  12. justify-content: space-between;
  13. position: absolute;
  14. bottom: 500rpx;
  15. left: 0;
  16. background: #fff;
  17. box-sizing: border-box;
  18. padding: 0 30rpx;
  19. line-height: 72rpx;
  20. box-shadow: 0 6rpx 12rpx rgba(0, 0, 0, 0.6); .picker-cancel, .picker-confirm {
  21. font-size: 30rpx;
  22. }
  23. .picker-cancel {
  24. color: #9E9E9E;
  25. }
  26. .picker-confirm {
  27. color: #018A56;
  28. }
  29. }
  30. .picker {
  31. width: 100%;
  32. height: 500rpx;
  33. position: absolute;
  34. bottom: 0;
  35. left: 0;
  36. background: #fff; .region-province, .region-city, .region-area {
  37. text-align: center;
  38. font-size: 24rpx;
  39. }
  40. }
  41. }

region.js

  1. const app = getApp();
  2. Component({
  3. /** * 组件的属性列表 */
  4. properties: {
  5. // 是否展示选择器
  6. showPicker: {
  7. type: Boolean,
  8. value: false
  9. },
  10. // 初始省市区数组
  11. initRegions: {
  12. type: Array,
  13. value: []
  14. }
  15. },
  16. /** * 组件的初始数据 */
  17. data: {
  18. // 当前省市区 0 省 1 市 2 区
  19. regions: [0, 0, 0],
  20. // 滑动选择器之前的省市区信息
  21. oldRegions: [0, 0, 0],
  22. // 上一次选中的省市区信息
  23. prevRegions: [0, 0, 0],
  24. // 省列表
  25. provinces: [],
  26. // 市列表
  27. citys: [],
  28. // 区列表
  29. areas: [],
  30. // 省
  31. province: {
  32. name: '',
  33. code: ''
  34. },
  35. // 市
  36. city: {
  37. name: '',
  38. code: ''
  39. },
  40. // 区
  41. area: {
  42. name: '',
  43. code: ''
  44. },
  45. // 是否展示
  46. show: false
  47. },
  48. lifetimes: {
  49. attached: function () {
  50. }
  51. },
  52. observers: {
  53. 'showPicker': function (value) {
  54. if (value) {
  55. this.setData({
  56. show: true
  57. })
  58. this.initPage();
  59. } else {
  60. this.setData({
  61. show: false
  62. })
  63. }
  64. }
  65. },
  66. /** * 组件的方法列表 */
  67. methods: {
  68. // 初始化页面
  69. initPage() {
  70. let regions = wx.getStorageSync('initRegions') || '';
  71. if (regions) {
  72. // 设置省
  73. app.api.region.index().then(res1 => {
  74. if (res1.code === 2000) {
  75. let data1 = res1.data;
  76. this.setData({
  77. provinces: data1.map(item => {
  78. return {
  79. name: item.name,
  80. code: item.rid
  81. }
  82. })
  83. })
  84. this.data.provinces.forEach((item, index) => {
  85. if (item.code === regions[0]) {
  86. this.setData({
  87. ['regions[0]']: index,
  88. ['oldRegions[0]']: index,
  89. ['prevRegions[0]']: index,
  90. province: {
  91. name: item.name,
  92. code: item.code
  93. }
  94. })
  95. // 设置市
  96. app.api.region.index({
  97. parent_id: regions[0]
  98. }).then(async res2 => {
  99. if (res2.code === 2000) {
  100. res2.data.forEach((item, index) => {
  101. this.setData({
  102. [`citys[${ this.data.citys.length}]`]: {
  103. name: item.name,
  104. code: item.rid
  105. }
  106. })
  107. if (item.rid === regions[1]) {
  108. this.setData({
  109. ['regions[1]']: index,
  110. ['oldRegions[1]']: index,
  111. ['prevRegions[1]']: index,
  112. city: {
  113. name: item.name,
  114. code: item.rid
  115. }
  116. })
  117. }
  118. })
  119. // 设置区
  120. await app.api.region.index({
  121. parent_id: regions[1]
  122. }).then(res3 => {
  123. if (res3.code === 2000) {
  124. res3.data.forEach((item, index) => {
  125. this.setData({
  126. [`areas[${ this.data.areas.length}]`]: {
  127. name: item.name,
  128. code: item.rid
  129. }
  130. })
  131. if (item.rid === regions[2]) {
  132. this.setData({
  133. ['regions[2]']: index,
  134. ['oldRegions[2]']: index,
  135. ['prevRegions[2]']: index,
  136. area: {
  137. name: item.name,
  138. code: item.rid
  139. },
  140. })
  141. }
  142. })
  143. } else if (res3.code === 2001) {
  144. app.deletetoken();
  145. } else {
  146. app.toast(res3.msg, 'none');
  147. }
  148. })
  149. } else if (res2.code === 2001) {
  150. app.deletetoken();
  151. } else {
  152. app.toast(res2.msg, 'none');
  153. }
  154. })
  155. }
  156. })
  157. } else if (res.code === 2001) {
  158. app.deletetoken();
  159. } else {
  160. app.toast(res.msg, 'none');
  161. }
  162. })
  163. } else {
  164. this.getProvinces();
  165. }
  166. },
  167. /** * 获取省 */
  168. async getProvinces() {
  169. await app.api.region.index().then(res => {
  170. if (res.code === 2000) {
  171. let data = res.data;
  172. let provinceList = data.map(item => {
  173. return {
  174. name: item.name,
  175. code: item.rid
  176. }
  177. })
  178. this.setData({
  179. provinces: provinceList
  180. })
  181. this.initCitysAreas();
  182. } else if (res.code === 2001) {
  183. app.deletetoken();
  184. } else {
  185. app.toast(res.msg, 'none');
  186. }
  187. })
  188. },
  189. /** * 省改变 * @param {number} code 省id */
  190. changeProvince(code) {
  191. app.api.region.index({
  192. parent_id: code
  193. }).then(res1 => {
  194. if (res1.code === 2000) {
  195. let data1 = res1.data;
  196. let cityList = data1.map(item => {
  197. return {
  198. name: item.name,
  199. code: item.rid
  200. }
  201. })
  202. this.setData({
  203. citys: cityList
  204. })
  205. app.api.region.index({
  206. parent_id: this.data.citys[0].code
  207. }).then(res2 => {
  208. if (res2.code === 2000) {
  209. let data2 = res2.data;
  210. let areaList = data2.map(item => {
  211. return {
  212. name: item.name,
  213. code: item.rid
  214. }
  215. })
  216. this.setData({
  217. areas: areaList
  218. })
  219. } else if (res2.code === 2001) {
  220. app.deletetoken();
  221. } else {
  222. app.toast(res2.msg, 'none');
  223. }
  224. })
  225. } else if (res1.code === 2001) {
  226. app.deletetoken();
  227. } else {
  228. app.toast(res1.msg, 'none');
  229. }
  230. })
  231. },
  232. /** * 市改变 * @param {number} code 市id */
  233. changeCity(code) {
  234. app.api.region.index({
  235. parent_id: code
  236. }).then(res => {
  237. if (res.code === 2000) {
  238. let data = res.data;
  239. let areaList = data.map(item => {
  240. return {
  241. name: item.name,
  242. code: item.rid
  243. }
  244. })
  245. this.setData({
  246. areas: areaList
  247. })
  248. } else if (res.code === 2001) {
  249. app.deletetoken();
  250. } else {
  251. app.toast(res.msg, 'none');
  252. }
  253. })
  254. },
  255. /** * 改变picker */
  256. changePicker(e) {
  257. let newRegion = e.detail.value;
  258. for (let i = 0; i < newRegion.length; i++) {
  259. // 找到改变的那一列
  260. if (newRegion[i] !== this.data.oldRegions[i]) {
  261. switch (i + 1) {
  262. case 1:
  263. // 省改变了
  264. this.changeProvince(this.data.provinces[newRegion[i]].code)
  265. this.setData({
  266. regions: [newRegion[i], 0, 0],
  267. oldRegions: [newRegion[i], 0, 0]
  268. })
  269. newRegion = [
  270. newRegion[0], 0, 0
  271. ]
  272. break;
  273. case 2:
  274. // 市改变了
  275. this.changeCity(this.data.citys[newRegion[i]].code)
  276. this.setData({
  277. regions: [this.data.oldRegions[0], newRegion[i], 0],
  278. oldRegions: [this.data.oldRegions[0], newRegion[i], 0]
  279. })
  280. break;
  281. case 3:
  282. // 区改变
  283. this.setData({
  284. regions: [this.data.oldRegions[0], this.data.oldRegions[1], newRegion[i]],
  285. oldRegions: [this.data.oldRegions[0], this.data.oldRegions[1], newRegion[i]]
  286. })
  287. break;
  288. }
  289. }
  290. }
  291. },
  292. /** * 初始化市区列表 */
  293. initCitysAreas() {
  294. // 获取市
  295. app.api.region.index({
  296. parent_id: this.data.provinces[this.data.regions[0]].code
  297. }).then(res1 => {
  298. if (res1.code === 2000) {
  299. let data1 = res1.data;
  300. let cityList = data1.map(item => {
  301. return {
  302. name: item.name,
  303. code: item.rid
  304. }
  305. })
  306. this.setData({
  307. citys: cityList
  308. })
  309. // 获取区
  310. app.api.region.index({
  311. parent_id: this.data.citys[this.data.regions[1]].code
  312. }).then(res2 => {
  313. if (res2.code === 2000) {
  314. let data2 = res2.data;
  315. let areaList = data2.map(item => {
  316. return {
  317. name: item.name,
  318. code: item.rid
  319. }
  320. })
  321. this.setData({
  322. areas: areaList,
  323. regions: this.data.regions
  324. })
  325. } else if (res2.code === 2001) {
  326. app.deletetoken();
  327. } else {
  328. app.toast(res2.msg, 'none');
  329. }
  330. })
  331. } else if (res1.code === 2001) {
  332. app.deletetoken();
  333. } else {
  334. app.toast(res1.msg, 'none');
  335. }
  336. })
  337. },
  338. /** * 隐藏选择器 */
  339. hidePicker() {
  340. this.setData({
  341. show: false,
  342. regions: this.data.prevRegions,
  343. oldRegions: this.data.prevRegions
  344. })
  345. },
  346. /** * 确定选择地址 */
  347. chooseRegion() {
  348. this.setData({
  349. province: {
  350. name: this.data.provinces[this.data.regions[0]].name,
  351. code: this.data.provinces[this.data.regions[0]].code
  352. },
  353. city: {
  354. name: this.data.citys[this.data.regions[1]].name,
  355. code: this.data.citys[this.data.regions[1]].code
  356. },
  357. area: {
  358. name: this.data.areas[this.data.regions[2]].name,
  359. code: this.data.areas[this.data.regions[2]].code
  360. },
  361. prevRegions: this.data.regions,
  362. })
  363. this.triggerEvent("chooseRegion", {
  364. initRegions: [this.data.province.code, this.data.city.code, this.data.area.code],
  365. region: this.data.province.name + ' ' + this.data.city.name + ' ' + this.data.area.name
  366. })
  367. wx.setStorageSync('initRegions', [this.data.province.code, this.data.city.code, this.data.area.code]);
  368. this.hidePicker();
  369. },
  370. }
  371. })

使用

wxml

  1. <region showPicker="{ {show.picker}}" initRegions="{ {initRegions}}" bind:chooseRegion="chooseRegion"></region>

js

  1. // pages/settled/settled.js
  2. const app = getApp();
  3. Page({
  4. /** * 页面的初始数据 */
  5. data: {
  6. // 选中的省市区id数组
  7. initRegions: [],
  8. // 常住地址
  9. region: '',
  10. // 展示控制
  11. show: {
  12. picker: false, // 地址选择器
  13. }
  14. },
  15. /** * 监听页面卸载 */
  16. onUnload: function() {
  17. wx.removeStorageSync('initRegions');
  18. },
  19. /** * 展示常住地址选择器 */
  20. showPicker() {
  21. this.setData({
  22. ['show.picker']: true
  23. })
  24. },
  25. /** * 选择常住地址 */
  26. chooseRegion(e) {
  27. this.setData({
  28. initRegions: e.detail.initRegions,
  29. region: e.detail.region
  30. })
  31. }
  32. })

效果

在这里插入图片描述

参考文档
picker-view | 微信开放文档
picker-view-column | 微信开放文档

发表评论

表情:
评论列表 (有 0 条评论,401人围观)

还没有评论,来说两句吧...

相关阅读

    相关 程序定义组件

    在写小程序的时候,有时候页面的内容过多,逻辑比较复杂,如果全部都写在一个页面的话,会比较繁杂,代码可读性比较差,也不易于后期代码维护,这时候可以把里面某部分功能抽出来,单独封装