Commit 6c87e93495dc021f6894bec7af4ab640c2908f15

Authored by fengtao
1 parent 3ede27b7

fix: DEFECT-415 修复app端密码无法点击

... ... @@ -16,8 +16,10 @@
16 16
17 17 <view class="form-row u-flex">
18 18 <u-input v-model="loginForm.password" :password="showPassword" placeholder="请输入登录密码" border="bottom">
19   - <template slot="suffix" @click="showPasswordMode">
20   - <view style="padding:10rpx"><u-icon width="18" height="14" :name="showPassword ? '/static/eye-hide.png' : '/static/eye.png'"></u-icon></view>
  19 + <template slot="suffix">
  20 + <view @click="showPasswordMode" style="padding:10rpx">
  21 + <u-icon width="18" height="14" :name="showPassword ? '/static/eye-hide.png' : '/static/eye.png'"></u-icon>
  22 + </view>
21 23 </template>
22 24 </u-input>
23 25 </view>
... ...
1 1 <template>
2   - <view class="u-input" :class="inputClass" :style="[wrapperStyle]">
3   - <view class="u-input__content">
4   - <view
5   - class="u-input__content__prefix-icon"
6   - v-if="prefixIcon || $slots.prefix"
7   - >
8   - <slot name="prefix">
9   - <u-icon
10   - :name="prefixIcon"
11   - size="18"
12   - :customStyle="prefixIconStyle"
13   - ></u-icon>
14   - </slot>
15   - </view>
16   - <view class="u-input__content__field-wrapper" @tap="clickHandler">
  2 + <view class="u-input" :class="inputClass" :style="[wrapperStyle]">
  3 + <view class="u-input__content">
  4 + <view class="u-input__content__prefix-icon" v-if="prefixIcon || $slots.prefix">
  5 + <slot name="prefix"><u-icon :name="prefixIcon" size="18" :customStyle="prefixIconStyle"></u-icon></slot>
  6 + </view>
  7 + <view class="u-input__content__field-wrapper" @tap="clickHandler">
17 8 <!-- 根据uni-appinput组件文档,H5APP中只要声明了password参数(无论true还是false)type均失效,此时
18 9 为了防止type=number时,又存在password属性,type无效,此时需要设置passwordundefined
19 10 -->
20   - <input
21   - class="u-input__content__field-wrapper__field"
22   - :style="[inputStyle]"
23   - :type="type"
24   - :focus="focus"
25   - :cursor="cursor"
26   - :value="innerValue"
27   - :auto-blur="autoBlur"
28   - :disabled="disabled || readonly"
29   - :maxlength="maxlength"
30   - :placeholder="placeholder"
31   - :placeholder-style="placeholderStyle"
32   - :placeholder-class="placeholderClass"
33   - :confirm-type="confirmType"
34   - :confirm-hold="confirmHold"
35   - :hold-keyboard="holdKeyboard"
36   - :cursor-spacing="cursorSpacing"
37   - :adjust-position="adjustPosition"
38   - :selection-end="selectionEnd"
39   - :selection-start="selectionStart"
40   - :password="password || type === 'password' || undefined"
41   - @input="onInput"
42   - @blur="onBlur"
43   - @focus="onFocus"
44   - @confirm="onConfirm"
45   - @keyboardheightchange="onkeyboardheightchange"
46   - />
47   - </view>
48   - <view
49   - class="u-input__content__clear"
50   - v-if="isShowClear"
51   - @tap="onClear"
52   - >
53   - <u-icon
54   - name="close"
55   - size="11"
56   - color="#ffffff"
57   - customStyle="line-height: 12px"
58   - ></u-icon>
59   - </view>
60   - <view
61   - class="u-input__content__subfix-icon"
62   - v-if="suffixIcon || $slots.suffix"
63   - >
64   - <slot name="suffix">
65   - <u-icon
66   - :name="suffixIcon"
67   - size="18"
68   - :customStyle="suffixIconStyle"
69   - ></u-icon>
70   - </slot>
71   - </view>
72   - </view>
73   - </view>
  11 + <input
  12 + class="u-input__content__field-wrapper__field"
  13 + :style="[inputStyle]"
  14 + :type="type"
  15 + :focus="focus"
  16 + :cursor="cursor"
  17 + :value="innerValue"
  18 + :auto-blur="autoBlur"
  19 + :disabled="disabled || readonly"
  20 + :maxlength="maxlength"
  21 + :placeholder="placeholder"
  22 + :placeholder-style="placeholderStyle"
  23 + :placeholder-class="placeholderClass"
  24 + :confirm-type="confirmType"
  25 + :confirm-hold="confirmHold"
  26 + :hold-keyboard="holdKeyboard"
  27 + :cursor-spacing="cursorSpacing"
  28 + :adjust-position="adjustPosition"
  29 + :selection-end="selectionEnd"
  30 + :selection-start="selectionStart"
  31 + :password="password === undefined ? undefined : password ? true : type === 'password' ? true : false"
  32 + @input="onInput"
  33 + @blur="onBlur"
  34 + @focus="onFocus"
  35 + @confirm="onConfirm"
  36 + @keyboardheightchange="onkeyboardheightchange"
  37 + />
  38 + </view>
  39 + <view class="u-input__content__clear" v-if="isShowClear" @tap="onClear"><u-icon name="close" size="11" color="#ffffff" customStyle="line-height: 12px"></u-icon></view>
  40 + <view class="u-input__content__subfix-icon" v-if="suffixIcon || $slots.suffix">
  41 + <slot name="suffix"><u-icon :name="suffixIcon" size="18" :customStyle="suffixIconStyle"></u-icon></slot>
  42 + </view>
  43 + </view>
  44 + </view>
74 45 </template>
75 46
76 47 <script>
77   -import props from "./props.js";
  48 +import props from './props.js';
78 49 /**
79 50 * Input 输入框
80 51 * @description 此组件为一个输入框,默认没有边框和样式,是专门为配合表单组件u-form而设计的,利用它可以快速实现表单验证,输入内容,下拉选择等功能。
... ... @@ -118,207 +89,199 @@ import props from "./props.js";
118 89 * @example <u-input v-model="value" :password="true" suffix-icon="lock-fill" />
119 90 */
120 91 export default {
121   - name: "u-input",
122   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
123   - data() {
124   - return {
125   - // 输入框的值
126   - innerValue: "",
127   - // 是否处于获得焦点状态
128   - focused: false,
129   - // value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化
130   - firstChange: true,
131   - // value绑定值的变化是由内部还是外部引起的
132   - changeFromInner: false,
  92 + name: 'u-input',
  93 + mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  94 + data() {
  95 + return {
  96 + // 输入框的值
  97 + innerValue: '',
  98 + // 是否处于获得焦点状态
  99 + focused: false,
  100 + // value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化
  101 + firstChange: true,
  102 + // value绑定值的变化是由内部还是外部引起的
  103 + changeFromInner: false,
133 104 // 过滤处理方法
134 105 innerFormatter: value => value
135   - };
136   - },
137   - watch: {
138   - value: {
139   - immediate: true,
140   - handler(newVal, oldVal) {
141   - this.innerValue = newVal;
142   - /* #ifdef H5 */
143   - // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法
144   - if (
145   - this.firstChange === false &&
146   - this.changeFromInner === false
147   - ) {
148   - this.valueChange();
149   - }
150   - /* #endif */
151   - this.firstChange = false;
152   - // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的
153   - this.changeFromInner = false;
154   - },
155   - },
156   - },
157   - computed: {
158   - // 是否显示清除控件
159   - isShowClear() {
160   - const { clearable, readonly, focused, innerValue } = this;
161   - return !!clearable && !readonly && !!focused && innerValue !== "";
162   - },
163   - // 组件的类名
164   - inputClass() {
165   - let classes = [],
166   - { border, disabled, shape } = this;
167   - border === "surround" &&
168   - (classes = classes.concat(["u-border", "u-input--radius"]));
169   - classes.push(`u-input--${shape}`);
170   - border === "bottom" &&
171   - (classes = classes.concat([
172   - "u-border-bottom",
173   - "u-input--no-radius",
174   - ]));
175   - return classes.join(" ");
176   - },
177   - // 组件的样式
178   - wrapperStyle() {
179   - const style = {};
180   - // 禁用状态下,被背景色加上对应的样式
181   - if (this.disabled) {
182   - style.backgroundColor = this.disabledColor;
183   - }
184   - // 无边框时,去除内边距
185   - if (this.border === "none") {
186   - style.padding = "0";
187   - } else {
188   - // 由于uni-app的iOS开发者能力有限,导致需要分开写才有效
189   - style.paddingTop = "6px";
190   - style.paddingBottom = "6px";
191   - style.paddingLeft = "9px";
192   - style.paddingRight = "9px";
193   - }
194   - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle));
195   - },
196   - // 输入框的样式
197   - inputStyle() {
198   - const style = {
199   - color: this.color,
200   - fontSize: uni.$u.addUnit(this.fontSize),
  106 + };
  107 + },
  108 + watch: {
  109 + value: {
  110 + immediate: true,
  111 + handler(newVal, oldVal) {
  112 + this.innerValue = newVal;
  113 + /* #ifdef H5 */
  114 + // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法
  115 + if (this.firstChange === false && this.changeFromInner === false) {
  116 + this.valueChange();
  117 + }
  118 + /* #endif */
  119 + this.firstChange = false;
  120 + // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的
  121 + this.changeFromInner = false;
  122 + }
  123 + }
  124 + },
  125 + computed: {
  126 + // 是否显示清除控件
  127 + isShowClear() {
  128 + const { clearable, readonly, focused, innerValue } = this;
  129 + return !!clearable && !readonly && !!focused && innerValue !== '';
  130 + },
  131 + // 组件的类名
  132 + inputClass() {
  133 + let classes = [],
  134 + { border, disabled, shape } = this;
  135 + border === 'surround' && (classes = classes.concat(['u-border', 'u-input--radius']));
  136 + classes.push(`u-input--${shape}`);
  137 + border === 'bottom' && (classes = classes.concat(['u-border-bottom', 'u-input--no-radius']));
  138 + return classes.join(' ');
  139 + },
  140 + // 组件的样式
  141 + wrapperStyle() {
  142 + const style = {};
  143 + // 禁用状态下,被背景色加上对应的样式
  144 + if (this.disabled) {
  145 + style.backgroundColor = this.disabledColor;
  146 + }
  147 + // 无边框时,去除内边距
  148 + if (this.border === 'none') {
  149 + style.padding = '0';
  150 + } else {
  151 + // 由于uni-app的iOS开发者能力有限,导致需要分开写才有效
  152 + style.paddingTop = '6px';
  153 + style.paddingBottom = '6px';
  154 + style.paddingLeft = '9px';
  155 + style.paddingRight = '9px';
  156 + }
  157 + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle));
  158 + },
  159 + // 输入框的样式
  160 + inputStyle() {
  161 + const style = {
  162 + color: this.color,
  163 + fontSize: uni.$u.addUnit(this.fontSize),
201 164 textAlign: this.inputAlign
202   - };
203   - return style;
204   - },
205   - },
206   - methods: {
  165 + };
  166 + return style;
  167 + }
  168 + },
  169 + methods: {
207 170 // 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
208 171 setFormatter(e) {
209   - this.innerFormatter = e
  172 + this.innerFormatter = e;
  173 + },
  174 + // 当键盘输入时,触发input事件
  175 + onInput(e) {
  176 + let { value = '' } = e.detail || {};
  177 + // 格式化过滤方法
  178 + const formatter = this.formatter || this.innerFormatter;
  179 + const formatValue = formatter(value);
  180 + // 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效
  181 + this.innerValue = value;
  182 + this.$nextTick(() => {
  183 + this.innerValue = formatValue;
  184 + this.valueChange();
  185 + });
  186 + },
  187 + // 输入框失去焦点时触发
  188 + onBlur(event) {
  189 + this.$emit('blur', event.detail.value);
  190 + // H5端的blur会先于点击清除控件的点击click事件触发,导致focused
  191 + // 瞬间为false,从而隐藏了清除控件而无法被点击到
  192 + uni.$u.sleep(50).then(() => {
  193 + this.focused = false;
  194 + });
  195 + // 尝试调用u-form的验证方法
  196 + uni.$u.formValidate(this, 'blur');
210 197 },
211   - // 当键盘输入时,触发input事件
212   - onInput(e) {
213   - let { value = "" } = e.detail || {};
214   - // 格式化过滤方法
215   - const formatter = this.formatter || this.innerFormatter
216   - const formatValue = formatter(value)
217   - // 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效
218   - this.innerValue = value
219   - this.$nextTick(() => {
220   - this.innerValue = formatValue;
221   - this.valueChange();
222   - })
223   - },
224   - // 输入框失去焦点时触发
225   - onBlur(event) {
226   - this.$emit("blur", event.detail.value);
227   - // H5端的blur会先于点击清除控件的点击click事件触发,导致focused
228   - // 瞬间为false,从而隐藏了清除控件而无法被点击到
229   - uni.$u.sleep(50).then(() => {
230   - this.focused = false;
231   - });
232   - // 尝试调用u-form的验证方法
233   - uni.$u.formValidate(this, "blur");
234   - },
235   - // 输入框聚焦时触发
236   - onFocus(event) {
237   - this.focused = true;
238   - this.$emit("focus");
239   - },
240   - // 点击完成按钮时触发
241   - onConfirm(event) {
242   - this.$emit("confirm", this.innerValue);
243   - },
244   - // 键盘高度发生变化的时候触发此事件
245   - // 兼容性:微信小程序2.7.0+、App 3.1.0+
  198 + // 输入框聚焦时触发
  199 + onFocus(event) {
  200 + this.focused = true;
  201 + this.$emit('focus');
  202 + },
  203 + // 点击完成按钮时触发
  204 + onConfirm(event) {
  205 + this.$emit('confirm', this.innerValue);
  206 + },
  207 + // 键盘高度发生变化的时候触发此事件
  208 + // 兼容性:微信小程序2.7.0+、App 3.1.0+
246 209 onkeyboardheightchange() {
247   - this.$emit("keyboardheightchange");
248   - },
249   - // 内容发生变化,进行处理
250   - valueChange() {
251   - const value = this.innerValue;
252   - this.$nextTick(() => {
253   - this.$emit("input", value);
254   - // 标识value值的变化是由内部引起的
255   - this.changeFromInner = true;
256   - this.$emit("change", value);
257   - // 尝试调用u-form的验证方法
258   - uni.$u.formValidate(this, "change");
259   - });
260   - },
261   - // 点击清除控件
262   - onClear() {
263   - this.innerValue = "";
264   - this.$nextTick(() => {
265   - this.valueChange();
266   - this.$emit("clear");
267   - });
268   - },
269   - /**
270   - * 在安卓nvue上,事件无法冒泡
271   - * 在某些时间,我们希望监听u-from-item的点击事件,此时会导致点击u-form-item内的u-input后
272   - * 无法触发u-form-item的点击事件,这里通过手动调用u-form-item的方法进行触发
273   - */
274   - clickHandler() {
275   - // #ifdef APP-NVUE
276   - if (uni.$u.os() === "android") {
277   - const formItem = uni.$u.$parent.call(this, "u-form-item");
278   - if (formItem) {
279   - formItem.clickHandler();
280   - }
281   - }
282   - // #endif
283   - },
284   - },
  210 + this.$emit('keyboardheightchange');
  211 + },
  212 + // 内容发生变化,进行处理
  213 + valueChange() {
  214 + const value = this.innerValue;
  215 + this.$nextTick(() => {
  216 + this.$emit('input', value);
  217 + // 标识value值的变化是由内部引起的
  218 + this.changeFromInner = true;
  219 + this.$emit('change', value);
  220 + // 尝试调用u-form的验证方法
  221 + uni.$u.formValidate(this, 'change');
  222 + });
  223 + },
  224 + // 点击清除控件
  225 + onClear() {
  226 + this.innerValue = '';
  227 + this.$nextTick(() => {
  228 + this.valueChange();
  229 + this.$emit('clear');
  230 + });
  231 + },
  232 + /**
  233 + * 在安卓nvue上,事件无法冒泡
  234 + * 在某些时间,我们希望监听u-from-item的点击事件,此时会导致点击u-form-item内的u-input后
  235 + * 无法触发u-form-item的点击事件,这里通过手动调用u-form-item的方法进行触发
  236 + */
  237 + clickHandler() {
  238 + // #ifdef APP-NVUE
  239 + if (uni.$u.os() === 'android') {
  240 + const formItem = uni.$u.$parent.call(this, 'u-form-item');
  241 + if (formItem) {
  242 + formItem.clickHandler();
  243 + }
  244 + }
  245 + // #endif
  246 + }
  247 + }
285 248 };
286 249 </script>
287 250
288 251 <style lang="scss" scoped>
289   -@import "../../libs/css/components.scss";
  252 +@import '../../libs/css/components.scss';
290 253
291 254 .u-input {
292   - @include flex(row);
293   - align-items: center;
294   - justify-content: space-between;
295   - flex: 1;
  255 + @include flex(row);
  256 + align-items: center;
  257 + justify-content: space-between;
  258 + flex: 1;
  259 +
  260 + &--radius,
  261 + &--square {
  262 + border-radius: 4px;
  263 + }
296 264
297   - &--radius,
298   - &--square {
299   - border-radius: 4px;
300   - }
  265 + &--no-radius {
  266 + border-radius: 0;
  267 + }
301 268
302   - &--no-radius {
303   - border-radius: 0;
304   - }
  269 + &--circle {
  270 + border-radius: 100px;
  271 + }
305 272
306   - &--circle {
307   - border-radius: 100px;
308   - }
  273 + &__content {
  274 + flex: 1;
  275 + @include flex(row);
  276 + align-items: center;
  277 + justify-content: space-between;
309 278
310   - &__content {
311   - flex: 1;
312   - @include flex(row);
313   - align-items: center;
314   - justify-content: space-between;
  279 + &__field-wrapper {
  280 + position: relative;
  281 + @include flex(row);
  282 + margin: 0;
  283 + flex: 1;
315 284
316   - &__field-wrapper {
317   - position: relative;
318   - @include flex(row);
319   - margin: 0;
320   - flex: 1;
321   -
322 285 &__field {
323 286 line-height: 26px;
324 287 text-align: left;
... ... @@ -327,27 +290,27 @@ export default {
327 290 font-size: 15px;
328 291 flex: 1;
329 292 }
330   - }
  293 + }
331 294
332   - &__clear {
333   - width: 20px;
334   - height: 20px;
335   - border-radius: 100px;
336   - background-color: #c6c7cb;
337   - @include flex(row);
338   - align-items: center;
339   - justify-content: center;
340   - transform: scale(0.82);
341   - margin-left: 4px;
342   - }
  295 + &__clear {
  296 + width: 20px;
  297 + height: 20px;
  298 + border-radius: 100px;
  299 + background-color: #c6c7cb;
  300 + @include flex(row);
  301 + align-items: center;
  302 + justify-content: center;
  303 + transform: scale(0.82);
  304 + margin-left: 4px;
  305 + }
343 306
344   - &__subfix-icon {
345   - margin-left: 4px;
346   - }
  307 + &__subfix-icon {
  308 + margin-left: 4px;
  309 + }
347 310
348   - &__prefix-icon {
349   - margin-right: 4px;
350   - }
351   - }
  311 + &__prefix-icon {
  312 + margin-right: 4px;
  313 + }
  314 + }
352 315 }
353 316 </style>
... ...