有的微信小程序开发者在做小程序时,使用到了 textarea这个小程序组件,然后点击页面上的某个元素,会触发页面弹起一个弹窗,这时发现 textarea的 placeholder文字或者输入的文字内容,会直接穿透遮罩层和浮动弹窗,显示在最上面。
那么这种情况要怎么解决?
小程序 textarea组件层级过高导致文字穿透浮层的解决方法 :
隐藏 textarea
这是最简单的解决手段,一般弹窗的时候,都会带个遮罩层,把遮罩层下面的内容隐藏一部分,用户基本上不会注意的,然后再去掉弹窗和遮罩层的时候再把 textarea显示出来。 这种方法简单有效,大部分情况下都可以这么解决。
textarea>
复制代码
使用替代元素
有时候, textarea穿透的不是遮罩层,或者遮罩层以一种半透明而非完全遮住页面内容的形式呈现,担心用户能够看到因为 textarea的消失而导致页面跳动,产生不好的用户体验,那么就可以使用替代元素来替代 textarea而非将之直接隐藏掉。
基本的 textarea组件只接受文本的输入,抛开可输入性的话,外观上看就是一个含有文本节点的简单元素,只需要获取当前状态下的 textarea中输入的文字,将之赋予给一个样式与 textarea相同的普通元素,就达到了临时替代的效果。
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的内容包含了换行文本,则需要对换行符进行处理:
textareaContent.replace(/\n/g, '
')
复制代码
如果你想让 textarea自动增加高度而不是固定高度,给 textarea加了个 auto-height,那么就需要“实时”获取其高度 说是 “实时”,其实也并不是那么实时,不考虑其他样式的变化, textarea的高度与行数有关,每增减一行,其高度才会变化,所以只需要监控其内容行数的变化即可,恰好 textarea组件也已经提供了这个监控器:bindlinechange。
原理说完了,完整实例代码如下:
index.wxml
切换maskbutton>
rich-text>
view>
view>
Footerbutton>
view>
view>
view>
复制代码
index.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可识别的换行元素
const txtRealContent = this.data.txtContent.replace(/\n/g, '
')
this.setData({ txtRealContent })
}
this.setData({ showMask: !this.data.showMask })
}
})
复制代码
index.wxss
.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;
}