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