原生微信小程序中封裝一個模擬select下拉框組件代碼示例
1.首先在components 里面設(shè)置組件名稱:van-select(隨便取名字);
2.新建文件寫代碼:
wxml:
<view class="w100 select_all_view"> <!-- 標題,可以沒有 --> <view class="mr-10 pt-10 size-28" style="width: {{titleWidth}};" wx:if="{{title}}">{{title}}</view> <view class="select_view relative" style="width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};max-width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};"> <view class="inputPlaceholder h100 w100 radius-10 relative flex_l pd-10 {{ disabled ? 'gray-3' : 'black' }}" bindtap="{{disabled || readonly ? '' : 'changeShow'}}" style="background: {{disabled ?'#f5f7fa' : bgColor}};border: 2rpx solid #ddd;"> <block wx:if="{{disabled || readonly}}"> <view class="flex-1" wx:if="{{selectLabel}}">{{selectLabel}}</view> <view class="flex-1 gray-3 line-1" wx:else>{{placeholder}}</view> <van-icon class="gray-3" name="arrow-down" /> </block> <block wx:else> <block wx:if="{{selectLabel}}"> <view class="flex-1">{{selectLabel}}</view> <van-icon class="gray-3" name="clear" wx:if='{{!show}}' catchtap="clearInput" /> <van-icon class="gray-3" name="arrow-up" wx:else /> </block> <block wx:else> <view class="flex-1 gray-3 line-1">{{placeholder}}</view> <van-icon class="gray-3" name="arrow-down" class="transfer {{show ? 'is-reverse' : 'no-reverse' }}" /> </block> </block> </view> <!-- 下拉展開后的可選擇內(nèi)容 --> <block wx:if='{{show}}'> <view class="{{toTop ? 'triangleBox-top' : 'triangleBox'}}"> <view class="{{toTop ? 'triangle-top' : 'triangle'}}"></view> </view> <view class="content radius-10 pd-20 size-28" style="{{toTop ? 'top: -' + (options.length > 4 ? 150 : (options.length * 30 + 40)) + 'rpx; margin-top: -6rpx;' : 'margin-top: 10rpx;'}}"> <view class="pd-10 center gray-3" wx:if="{{options.length < 1}}">暫無數(shù)據(jù)</view> <view class="line-1 w100 pd-10 contentItem {{item[valueName] == selectValue ? 'bold':''}}" wx:for="{{options}}" wx:key="index" bindtap="handleChange" data-item="{{item}}" style="color: {{ item[valueName] == selectValue ? textColor : '#000'}}; background: {{item[valueName] == selectValue ? itemBgColor:''}};"> {{item[labelName]}} </view> </view> </block> </view> </view>
wxss:
.select_all_view { display: flex; justify-content: start; align-items: start; z-index: 999; margin-bottom: 20rpx; } .select_view { /* min-width: 200rpx; */ min-height: 64rpx; } .inputPlaceholder { font-size: 28rpx; } .flex_l{ display: flex; } .flex-1{ flex: 1; } .pd-10{ padding:20rpx; } .relative{ position: relative; } .radius-10{ border-radius: 10rpx; } .icon { position: absolute; right: 12rpx; top: 20rpx; } .contentItem { height: 30rpx; line-height: 30rpx; font-size: 24rpx; } .content { width: calc(100% - 4px); margin-left: 2px; position: absolute; z-index: 999; max-height: 150rpx; background: #FFFFFF; /* border: 1px solid #ccc; */ box-shadow: 0 0 4px #ccc; opacity: 1; /* margin-top: 10rpx; */ overflow-x: hidden; overflow-y: scroll; } .triangleBox { position: absolute; z-index: 1000; left: 30rpx; } .triangle { position: relative; border-left: 12rpx solid transparent; border-right: 12rpx solid transparent; border-bottom: 10rpx solid #ccc; } .triangle::after { content: ''; position: absolute; top: 3rpx; left: -12rpx; border-left: 12rpx solid transparent; border-right: 12rpx solid transparent; border-bottom: 10rpx solid #fff; } .triangleBox-top { position: absolute; z-index: 1000; left: 30rpx; /* display: none; */ } .triangle-top { position: relative; border-left: 12rpx solid transparent; border-right: 12rpx solid transparent; border-top: 10rpx solid #ccc; } .triangle-top::after { content: ''; position: absolute; bottom: 3rpx; left: -12rpx; border-left: 12rpx solid transparent; border-right: 12rpx solid transparent; border-top: 10rpx solid #fff; } .is-reverse { transform: rotate(180deg); } .transfer { transition: transform .3s; } .no-reverse { transition: rotate(0deg); }
js:
Component({ options: { addGlobalClass: true, }, properties: { /* --------- 樣式參數(shù) --------- */ titleWidth: { // 標題長度 type: String, value: "60px" }, bgColor: { // 輸入框背景顏色 type: String, value: "#fff" }, itemBgColor: { // 選中的選項背景顏色 type: String, value: "#F5F8FE" }, textColor: { // 選中的字體顏色 type: String, value: "#FF5733" }, /* --------- 數(shù)據(jù)參數(shù) --------- */ title: { // 下拉框標題 type: String, value: "" }, number: { // 下拉框標題 type: String, value: "" }, options: { // 選項數(shù)組 type: Array, value: [], }, labelName: { // 選項數(shù)組-綁定的label名稱 type: String, value: "dictLabel", }, valueName: { // 選項數(shù)組-綁定的value名稱 type: String, value: "dictValue" }, modelValue: { // 綁定的value type: String, value: "", observer: function () { //如果有默認值,需要匹配出name,所以這里使用obersver,當父組件中值改變時觸發(fā) this.handleData(); } }, placeholder: { // 輸入框為空時占位符 type: String, value: "請選擇" }, disabled: { // 是否禁用 type: Boolean, value: false }, readonly: { // 是否只讀 type: Boolean, value: false } }, /** * 頁面的初始數(shù)據(jù) */ data: { show: false, //選項框及圖標展示 selectValue: "", //選中的value selectLabel: "", //選中的label toTop: false, // 下拉框是否展示在輸入框上方 }, attached() { this.handleData() }, methods: { // 清空輸入框 clearInput() { this.setData({ selectValue: "", //選中的value selectLabel: "", //選中的label show: false, }) }, // 下拉框收起和展開 changeShow(e) { let that = this const query = wx.createSelectorQuery(); // 選擇當前點擊的 view 元素 query.select('.inputPlaceholder'+this.data.number).boundingClientRect(); query.exec(function (res) { // res[0].bottom 是元素距離可視區(qū)域頂部的距離加上元素自身的高度; res[1].scrollTop 是頁面的滾動距離 var show = !that.data.show if (res[0]) { /* that.triggerEvent("handleShow", show); // [暫未發(fā)現(xiàn)]處理滾動選項區(qū)域時背景頁面滾動問題 */ let toBottom = wx.getSystemInfoSync().windowHeight - res[0].bottom; console.log('距離設(shè)備底部的距離:', toBottom); that.setData({ toTop: toBottom < 150 ? true : false, show: show }) } else { that.setData({ show: show }) } }); }, // 選擇數(shù)據(jù)后回顯 handleChange(e) { let { item } = e.currentTarget.dataset let { labelName, valueName } = this.data this.setData({ selectValue: item[valueName], selectLabel: item[labelName], show: false }) let obj = {} obj[valueName] = item[valueName] obj[labelName] = item[labelName] this.triggerEvent("handleChange", obj);// 傳參 }, // 匹配值并回顯 handleData() { let { modelValue, options, valueName, labelName } = this.properties; if (modelValue) { let item = options.find(r => r[valueName] == modelValue) this.setData({ selectLabel: item ? item[labelName] : modelValue, selectValue: modelValue, }); } } } })
json:
{ "component": true, "usingComponents": {} }
以上就是組件的全部代碼,當然你也可以自己再按照需求改造,接下來就是組件的應(yīng)用:
組件應(yīng)用:
1.在所需要用組件的頁面中引入組件,在所需頁面的json中:
{ "navigationBarTitleText": "", "usingComponents": { "wan-select": "../components/van-select/index" } }
2.在wxml里面使用:
<view class="cont-box"> <wan-select class="inputPlaceholder1" options="{{options1}}" number="1" labelName="text" valueName="id" modelValue="{{selectedId1}}" placeholder="請選擇" bindhandleChange="handleChange" title="" readonly="{{false}}" disabled="{{options1.length == 0}}"></wan-select> </view>
說明:
- class="inputPlaceholder1" (自己寫的類,可以修改樣式)
- options="{{options1}}"(下拉框的選項數(shù)據(jù))
- labelName="text"(選項數(shù)組-綁定的label名稱)
- valueName="id"(選項數(shù)組-綁定的value名稱)
- number="1"(自定義的值,多個select 有關(guān)聯(lián)的情況下,添加,根據(jù)自己需求,一個的話沒必要)
- modelValue="{{selectedId1}}"(為了回顯下拉框數(shù)據(jù)中選中的項)
- bindhandleChange="handleChange"(操作事件)
- title="" (下拉框左側(cè)添加名稱)
- readonly="{{false}}"(是否只讀)
- disabled="“(是否禁用)
如圖所示:
總結(jié)
到此這篇關(guān)于原生微信小程序中封裝一個模擬select下拉框組件的文章就介紹到這了,更多相關(guān)微信小程序封裝模擬select下拉框組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談javascript中的數(shù)據(jù)類型轉(zhuǎn)換
本文主要對javascript中的數(shù)據(jù)類型轉(zhuǎn)換進行介紹,具有一定的參考價值,下面跟著小編一起來看下吧2016-12-12JavaScript Generator函數(shù)使用分析
生成器Generator是JavaScript ES6引入的特性,它讓我們可以分段執(zhí)行一個函數(shù)。但是在談?wù)撋善鳎℅enerator)之前,我們要先了解迭代器Iterator2022-10-10Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實例(超簡單)
Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實例(超簡單),需要的朋友可以參考一下2013-06-06對字符串進行HTML編碼和解碼的JavaScript函數(shù)
對字符串進行HTML編碼和解碼的JS函數(shù),記下了方便以后找 :)2010-02-02VS?Code中JavaScript環(huán)境搭建配置全過程
node.js大部分基本模塊都用JavaScript語言編寫,JavaScript最早是運行在瀏覽器中,通常作為客戶端程序設(shè)計語言使用,node.js的出現(xiàn)使JavaScript也能用于服務(wù)端編程,這篇文章主要給大家介紹了關(guān)于VS?Code中JavaScript環(huán)境搭建配置的相關(guān)資料,需要的朋友可以參考下2024-02-02