⼩程序—⾃定义picker选择器弹窗内容+textarea穿透bug ⼩程序中定义好的⼏种picker选择器,不管是⽇期选择器还是地区选择器,或是其他的都只有定死的样式和内容。
但是⼤多数开发程序的情况下还是需要⾃⼰写样式的,或是内容的。
例如:
代码如下:
<view class="free-btns" >
<button class="free-btn" bindtap="toggleDialog">
选定国家:{{value}}
</button>
</view>
<view class="free-dialog {{ showDialog ? 'free-dialog--show' : '' }}">
<view class="free-dialog__mask" bindtap="toggleDialog"/>
<view class="free-dialog__container">
<view >
<form bindsubmit='submit' bindreset="reset">
<view bindtap='freetoBack' class="free-button free-dialog-reset">取消</view>
<view bindtap='freeBack' class="free-button free-dialog-submit">确定</view>
<radio-group class='free-radios' bindchange="radioChange">
<label class="free-radio" bindtap="click" wx:for="{{items}}" wx:key="{{items}}" data-id="{{index}}" > <radio value="{{item.name}}" name="{{item.value}}"></radio>
<label class="free-text">{{item.value}}</label>
</label>
</radio-group>
</form>
</view>
</view>
</view>
样式:
.free-dialog__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.free-dialog__container {
position: fixed;
left: 0;
bottom: 0;
width: 750rpx;
background: white;
transform: translateY(150%);
transition: all 0.4s ease;
z-index: 11;
}
.free-dialog--show .free-dialog__container {
transform: translateY(0);
}
.free-dialog--show .free-dialog__mask {
display: block;
}
/*模态框中的内容*/
.free-button{
display: inline-block;
width:50px;
text-align: center;
font-size:20px;
color:#707070;
margin-bottom:20px;
}
.free-dialog-submit{
float: right;
color:#48c23d;
}
radio-group{
margin:10rpx 0rpx;
}
radio-group>label{
width:22.5%;
display: inline-block;
border:1px solid #ddd;
padding:10px 0px;
margin:0px 2px 2px;
}
radio-group label radio{
width:100%;
z-index: 3;
display: none;
}
.checked{
background:#48c23d;
color:#fff;
}
radio-group label .free-text{
width:100%;
text-align: center;
display: inline-block;
}
js:
Page({
data: {
showDialog: false,
items: [
{ name: '中国', value: '中国' },
{ name: '美国', value: '美国' },
{ name: '巴西', value: '巴西' },
{ name: '⽇本', value: '⽇本' },
{ name: '英国', value: '英国' },
{ name: '法国', value: '法国' },
{ name: '韩国', value: '韩国' },
{ name: '俄罗斯', value: '俄罗斯' },]
/*点击变⾊*/
click:function(e){
var id = e.currentTarget.dataset.id
var that = this
that.setData({
id:id
})
},
onLoad: function (options) {
var that = this
that.setData({
value:'show'
})
},
radioChange: function (e) {
console.log('radio发⽣change事件,携带value值为:', e.detail.value)
自动弹窗代码var that = this
that.setData({
value: e.detail.value
})
console.log(this.data.value)
},
toggleDialog() {
this.setData({
showDialog: !this.data.showDialog
});
},
freeBack:function(){
var that = this
if(this.data.value=='show'){
wx.showModal({
title: '提⽰',
content: '你没有选择任何内容',
})
}
that.setData({
showDialog: !this.data.showDialog
})
},
freetoBack: function () {
var that = this
wx.showModal({
title: '提⽰',
content: '你没有选择任何内容',
})
that.setData({
showDialog: !this.data.showDialog,
value:'show',
checked: false,
})
},
})
遇到个BUG,就是表单中有textarea组件的时候,弹出层设置z-index,在模拟器上运⾏没问题,但是真机就⽆效了,textarea的内容就会穿透出来。
查了资料发现是官⽅的坑,textarea组件为原⽣组件层级最⾼,不能通过 z-index 控制层级。
解决办法:
1、隐藏textarea:
设置⼀个值,⽤wx:if 去控制textarea的显⽰和隐藏。就是说当弹窗弹出的时候,在textarea做wx:if判断那个值为false,把textarea隐藏,然后关闭弹窗或点击其他的时候,把那个
值再设为true,显⽰textarea。当然hidden原理⼀样。
代码如下:
<view class='itemArea'>
<view class="form_item">留⾔类型:</view>
<view class="form_item flex_row jc_between underLine">
<button class="free-btn" bindtap="toggleType">
{{typename}}
</button>
<view class="red" bindtap="toggleType">选择</view>
</view>
<view bindtap="hideView">
<view class="free-dialog {{ showType ? 'free-dialog-show' : 'free-dialog_mask' }}">
<view class="free-dialog_mask" bindtap="toggleType" />
<view class="free-dialog_container1">
<view class='p25'>
<form bindsubmit='submit' bindreset="reset">
<radio-group class='free-radios' bindchange="radioChange2">
<label class="free-radio" bindtap="clickType" wx:for="{{msgtype}}" wx:key="{{msgtype}}" data-idn="{{index}}" data-name='{{pename}}' data-id='{{peid}}' {{pename}}" name="{{pename}}"></radio>
<label class="free-text">{{pename}}</label>
</label>
</radio-group>
</form>
</view>
</view>
</view>
</view>
</view>
<view class='pb20'>
<view class="form_item">留⾔内容:</view>
<view class="form_item">
<textarea class='form_textarea' hidden="{{noTextarea}}" placeholder='请填写留⾔内容' bindinput='msgcontent' value="{{msgcontent}}" name="msgcontent"></textarea>
</view>
</view>
js:
data: {
noTextarea: false, //textarea弹出层的时候隐藏
},
//点击其他位置隐藏遮罩层
hideView:function(){
var that = this;
that.setData({
noTextarea: false,
})
},
//选择留⾔类型
toggleType: function () {
this.setData({
showType: !this.data.showType,
noTextarea: true,
},
radioChange2: function (e) {
var that = this;
that.setData({
typename: e.detail.value,
showType: !this.data.showType,
noTextarea: false,
})
console.log(pename);
},
clickType:function(e){
var that = this;
var idn = e.currentTarget.dataset.idn;
var id = e.currentTarget.dataset.id;
that.setData({
idn: idn,
typeid: id,
noTextarea: false,
})
console.log(peid);
},
2、还有⼀种解决⽅法是使⽤替代元素
有时候,textarea穿透的不是遮罩层,或者遮罩层以⼀种半透明⽽⾮完全遮住页⾯内容的形式呈现,担⼼⽤户能够看到因为textarea的消失⽽导致页⾯跳动,产⽣不好的⽤户体验,那么就可以使⽤替代元素来替代textarea⽽⾮将之直接隐藏掉。
基本的textarea组件只接受⽂本的输⼊,抛开可输⼊性的话,外观上看就是⼀个含有⽂本节点的简单元素,只需要获取当前状态下的textarea中输⼊的⽂字,将之赋予给⼀个样式与textarea相同的普通元素,就达到了临时替代的效果。
<!-- 这是真正的 textarea组件 -->
<textarea id="text-area" value="{{txtRealContent}}" bindinput='txtInput' wx:if="{{!showMask}}"/>
<!-- 这是⽤于模拟 textarea的替代元素 -->
<view class='rich-text' wx:else>
<rich-text nodes="{{txtRealContent}}"></rich-text>
</view>
由于需要实时获取textarea中已经输⼊的内容,所以给textarea元素加了个bindinput的
showMask⽤于标识是否显⽰遮罩层(或者其他可能会被 textarea穿透的浮动元素),如果显⽰遮罩层,则隐藏textarea元素,并显⽰替代原宿
这⾥textarea的隐藏使⽤了wx:if,会使其彻底地从页⾯中消失,⽽重新显⽰出来的时候,textarea元素会重新创建,丢失原先输⼊,所以给其加了个value属性,其值txtRealContent就是缓存的textarea已经输⼊的⽂本内容;如果你不⽤这种⽅法,不让textarea完全显⽰,⽽仅仅是隐藏,例如使⽤hidden="{{ showMask ? true :false }}",因为不涉及到textarea的删除与重建,所以就⽆需添加value属性来控制⽂本内容了。
textarea是可以输⼊可换⾏的⽂本内容的,所以这⾥使⽤了rich-text组件,在使⽤的时候,我发现rich-text好像不⽀持溢出隐藏,所以⼜额外在其外⾯包了⼀层view组件,并将其⾼度设置为和textarea相同。
上⾯四个步骤,都⽐较简单,稍微需要注意的是,如果textarea的内容包含了换⾏⽂本,则需要对换⾏符进⾏处理:
如果你想让textarea⾃动增加⾼度⽽不是固定⾼度,给textarea加了个auto-height,那么就需要“实时”获取其⾼度说是 “实时”,其实也并不是那么实时,不考虑其他样式的变化,textarea的⾼度与⾏数有关,每增减⼀⾏,其⾼度才会变化,所以只需要监控其内容⾏数的变化即可,恰好textarea组件也已经提供了这个监控器:bindlinechange。
实例代码如下:
<view class="page-body">
<button bindtap="changeMaskVisible">切换mask</button>
<view class="textarea-wrp">
<textarea id="text-area" value="{{txtContent}}" bindinput='txtInput' bindlinechange="textAreaLineChange" wx:if="{{!showMask}}" auto-height />
<view class='rich-text' wx:else>
<rich-text nodes="{{txtRealContent}}"></rich-text>
</view>
</view>
<button>Footer</button>
<view wx:if="{{showMask}}" bindtap="changeMaskVisible" class="mask">
<view class="mask-content"></view>
</view>
</view>
样式:
.rich-text {
overflow: hidden;
}
.
mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .6);
z-index: 10;
}
.mask-content {
position: fixed;
top: 44%;
left: 50%;
height: 60%;
width: 60%;
transform: translate(-50%, -50%);
background-color: yellowgreen;
z-index: 12;
}
js:
Page({
data: {
txtRealContent: '',
txtContent: '',
showMask: false,
txtHeight: 0
},
textAreaLineChange(e) {
this.setData({ txtHeight: e.detail.height })
},
txtInput(e) {
this.setData({ txtContent: e.detail.value })
},
changeMaskVisible(e) {
if (!this.data.showMask) {
// 将换⾏符转换为wxml可识别的换⾏元素 <br/>
const txtRealContent = place(/\n/g, '<br/>')
this.setData({ txtRealContent })
}
this.setData({ showMask: !this.data.showMask })
}
})

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。