微信小程序封装bindinput & 输入框出现清空图标 & wx:key对input的影响
Q:我以前写小程序每次获取输入内容,都要写一个方法,觉得十分麻烦,所以写了一个通用的方法。
A:我能想到的原理就是,不同的input所带的data不同,bindinput事件setData不同的data。
<input class="weui-input" bindinput="bindKeyInput" data-inputName='telephone' placeholder="请输入电话号码"/>
// 获取输入框的内容,封装起来,根据data-的值去渲染不同的data
bindKeyInput: function (e) {
let inputName = e.currentTarget.dataset.inputname;
this.setData({
[inputName]: e.detail.value
})
},
Q:最近项目有一个需求,就是点击输入框时右边显示清空图标。
A:我的思路是:好好利用bindfocus和bindblur,聚焦函数和非聚焦函数。聚焦时显示清空图标,非聚焦时隐藏清空图标。
// 清空输入框的内容 // 聚焦函数:如果字符串长度为0,则不显示清空图标,否则显示清空图标。 bindKeyFocus: function (e) { let index = e.currentTarget.dataset.index; let fullInputName = `local.is_clear_icon[${index}]`; let inputLength = e.detail.value.length; inputLength == 0 ? this.setData({ [fullInputName]: true }) : this.setData({ [fullInputName]: false }) }, // 非聚焦函数:隐藏清空图标 bindKeyBlur: function (e) { let index = e.currentTarget.dataset.index; let inputName = e.currentTarget.dataset.inputname; let fullInputName = `local.is_clear_icon[${index}]`; let fullInputName2 = `local.${inputName}[0]`; let value = e.detail.value; if (this.data.local.test) { value = [""]; this.setData({ "local.test": false }); } this.setData({ [fullInputName]: true, [fullInputName2]: value }); }, // 点击图标清空 clearInput: function (e) { let inputName = e.currentTarget.dataset.inputname; let fullInputName = `local.${inputName}`; console.log(e.currentTarget.dataset.inputname, fullInputName) let index = e.currentTarget.dataset.index; let clearIcon = `local.focus[${index}]`; this.setData({ [fullInputName]: [""], [clearIcon]: false, "local.test": true }) },
//名字输入
<block wx:for="{{name}}" wx:key="idx" wx:for-index="idx"> <view class="weui-cell weui-cell_input"> <view class="weui-cell__hd wh-card-list-item"> <view class="weui-label wh-required" wx:if="{{idx == 0}}">姓名</view> </view> <view class="weui-cell__bd clear-input-father weui-flex" wx:if="{{idx == 0}}"> <input class="weui-input" data-inputName='name' placeholder="你的姓名" bindinput="bindKeyInput" value='{{item}}' bindfocus="bindKeyFocus" data-index="0" bindblur="bindKeyBlur"/> <icon class='clear-input' type="clear" size="20" hidden='{{is_clear_icon[0]}}' data-inputName='name' data-index="0" catchtap='clearInput'/> </view> <view class="weui-cell__bd clear-input-father weui-flex wh-white-space" wx:else> <view class='wh-white-space' data-index='{{idx}}' data-inputName='name' catchtap='chooseItem'>{{item}}</view> <icon class='clear-input' type="clear" size="20" data-index='{{idx}}' data-inputName='name' catchtap='deteleItem'/> </view> </view> </block>
//手机号输入 <block wx:for="{{telephone}}" wx:key="*this" wx:for-index="idx"> <view class="weui-cell weui-cell_input"> <view class="weui-cell__hd wh-card-list-item"> <view class="weui-label wh-required" wx:if="{{idx == 0}}">手机号</view> </view> <view class="weui-cell__bd clear-input-father weui-flex" wx:if="{{idx == 0}}"> <input class="weui-input" type='number' placeholder="你的手机号" bindinput="bindKeyInput" data-inputName='telephone' value='{{item}}' bindfocus="bindKeyFocus" data-index="1" bindblur="bindKeyBlur" /> <icon class='clear-input' type="clear" size="20" hidden='{{is_clear_icon[1]}}' data-inputName='telephone' data-index="1" catchtap='clearInput'/> </view> <view class="weui-cell__bd clear-input-father weui-flex wh-white-space" wx:else> <view class='wh-white-space' data-index='{{idx}}' data-inputName='telephone' catchtap='chooseItem'>{{item}}</view> <icon class='clear-input' type="clear" size="20" data-index='{{idx}}' data-inputName='telephone' catchtap='deteleItem'/> </view> </view> </block>
Q:使用wx:for=“{{name}}”去渲染input输入框,而input输入框又修改了name的内容,这样会出现一种情况:用户一输入之后,input便失去聚焦。
A:个人观点:bindinput动态改变name的值,会重新渲染整个html代码。wx:key值设置值不对,改为wx:key="index"即可。
<block wx:for="{{name}}" wx:key="idx" wx:for-index="idx"> <view class="weui-cell weui-cell_input"> <view class="weui-cell__hd wh-card-list-item"> <view class="weui-label wh-required" wx:if="{{idx == 0}}">姓名</view> </view> <view class="weui-cell__bd clear-input-father weui-flex" wx:if="{{idx == 0}}"> <input class="weui-input" data-inputName='name' placeholder="你的姓名" bindinput="bindKeyInput" value='{{item}}' bindfocus="bindKeyFocus" data-index="0" bindblur="bindKeyBlur"/> <icon class='clear-input' type="clear" size="20" hidden='{{is_clear_icon[0]}}' data-inputName='name' data-index="0" catchtap='clearInput'/> </view> <view class="weui-cell__bd clear-input-father weui-flex wh-white-space" wx:else> <view class='wh-white-space' data-index='{{idx}}' data-inputName='name' catchtap='chooseItem'>{{item}}</view> <icon class='clear-input' type="clear" size="20" data-index='{{idx}}' data-inputName='name' catchtap='deteleItem'/> </view> </view> </block>
下面这种就会失去聚焦:
<block wx:for="{{telephone}}" wx:key="*this" wx:for-index="idx"> <view class="weui-cell weui-cell_input"> <view class="weui-cell__hd wh-card-list-item"> <view class="weui-label wh-required" wx:if="{{idx == 0}}">手机号</view> </view> <view class="weui-cell__bd clear-input-father weui-flex" wx:if="{{idx == 0}}"> <input class="weui-input" type='number' placeholder="你的手机号" bindinput="bindKeyInput" data-inputName='telephone' value='{{item}}' bindfocus="bindKeyFocus" data-index="1" bindblur="bindKeyBlur" /> <icon class='clear-input' type="clear" size="20" hidden='{{is_clear_icon[1]}}' data-inputName='telephone' data-index="1" catchtap='clearInput'/> </view> <view class="weui-cell__bd clear-input-father weui-flex wh-white-space" wx:else> <view class='wh-white-space' data-index='{{idx}}' data-inputName='telephone' catchtap='chooseItem'>{{item}}</view> <icon class='clear-input' type="clear" size="20" data-index='{{idx}}' data-inputName='telephone' catchtap='deteleItem'/> </view> </view> </block>
这里主要是wx:key的应用:源于http://www.wxappclub.com/topic/536
wx:key
的值以两种形式提供
- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
1:有wx:key
的情况(不重新创建,仅改变顺序)
添加元素或改变元素顺序导致数据改变时,
会校正带有Key的组件(可通过key识别各组件),
框架会根据“目前数据”,重新排序各组件,而不是重新创建,
使组件保持自身的状态,列表渲染效率高。
2:无wx:key
的情况(重新创建)
添加元素或改变元素顺序导致数据改变时,
此时各组件没有key(无法识别各组件)
框架会被迫根据“目前数据”重新创建各组件,
使组件重置初始状态(原有状态自然被清空),列表渲染效率低。
B:两种情况的对比
wk:key | 组件识别 | 渲染情况 | 状态情况 | for效率 |
---|---|---|---|---|
有 | 各组件可识别 | 渲染时仅改变组件顺序 | 保持组件之前原来状态 | 效率高 |
无 | 组件无法识别 | 渲染时重新创建各组件 | 重置组件的初始状态 | 效率低 |