diff --git a/example/pages/field/config.js b/example/pages/field/config.js
deleted file mode 100644
index ee14e6f1..00000000
--- a/example/pages/field/config.js
+++ /dev/null
@@ -1,68 +0,0 @@
-module.exports = {
- // 基础类型输入框配置
- base: {
- name: {
- focus: true,
- title: '收货人',
- placeholder: '名字'
- },
- tel: {
- error: true,
- title: '联系电话',
- inputType: 'number',
- placeholder: '请输入手机号'
- },
- address: {
- title: '详细地址',
- type: 'textarea',
- placeholder: '请输入详细地址(最多50字)'
- },
- disabled: {
- title: '用户信息',
- disabled: true,
- value: '输入框已禁用'
- }
- },
- // 无标题输入框
- notitle: {
- placeholder: '请输入收货人姓名',
- componentId: 'textarea:test'
- },
- // 圆角输入框
- radius: {
- totalPrice: {
- right: true,
- mode: 'wrapped',
- title: '消费总额',
- inputType: 'number',
- placeholder: '询问收银员后输入'
- },
- excludePrice: {
- right: true,
- error: true,
- mode: 'wrapped',
- title: '不参与优惠金额',
- inputType: 'number',
- placeholder: '询问收银员后输入'
- },
- notitle: {
- mode: 'wrapped',
- inputType: 'number',
- placeholder: '请输入消费金额'
- }
- },
- // Form 中使用输入框
- form: {
- name: {
- name: 'name',
- placeholder: '请输入收货人姓名',
- componentId: 'form:test:name'
- },
- tel: {
- name: 'tel',
- inputType: 'tel',
- placeholder: '请输入收货人手机号码',
- componentId: 'form:test:tel'
- }
- }
-};
diff --git a/example/pages/field/index.js b/example/pages/field/index.js
index 28ef3a4b..28075b3e 100644
--- a/example/pages/field/index.js
+++ b/example/pages/field/index.js
@@ -1,82 +1,18 @@
-const config = require('./config');
-
Page({
data: {
- config,
- value: 'test',
- textareaValue: 'test textarea',
- area: ['省份', '北京市', '天津市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省', '上海市', '江苏省', '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省', '广东省', '广西壮族自治区', '海南省', '重庆市', '四川省', '贵州省', '云南省', '西藏自治区', '陕西省', '甘肃省', '青海省', '宁夏回族自治区', '新疆维吾尔自治区', '台湾省', '香港特别行政区', '澳门特别行政区'],
- areaIndex: 0,
- // picker-view 示例配置
- pickerViewConfig: {
- show: false,
- value: [0, 0],
- year: [2016, 2017, 2018],
- sex: ['男', '女']
- }
+ sms: '',
+ value: '',
+ password: '',
+ username: '',
+ username2: '',
+ message: '',
+ phone: '1365577'
},
- onAreaChange(e) {
- this.setData({
- areaIndex: e.detail.value
- });
- },
-
- handleZanFieldChange(e) {
- const { detail } = e;
-
- console.log('[zan:field:change]', detail);
- },
-
- handleZanFieldFocus(e) {
- const { detail } = e;
-
- console.log('[zan:field:focus]', detail);
- },
-
- handleZanFieldBlur(e) {
- const { detail } = e;
-
- console.log('[zan:field:blur]', detail);
- },
-
- clearInput() {
- this.setData({
- value: ''
- });
- },
-
- clearTextarea() {
- this.setData({
- textareaValue: ''
- });
- },
-
- formSubmit(event) {
- console.log('[zan:field:submit]', event.detail.value);
- },
-
- formReset(event) {
- console.log('[zan:field:reset]', event);
- },
-
- /* piker-view 示例相关函数 */
- handleDateFieldClick() {
- this.setData({
- 'pickerViewConfig.show': true
- });
- },
-
- handlePopupDateChange(e) {
- this.setData({
- 'pickerViewConfig.value': e.detail.value
- });
- },
-
- hideDatePopup() {
- this.setData({
- 'pickerViewConfig.show': false
+ onTapIcon() {
+ wx.showToast({
+ icon: 'none',
+ title: '点击图标'
});
}
-
});
diff --git a/example/pages/field/index.json b/example/pages/field/index.json
index d88f1555..4477ae8a 100644
--- a/example/pages/field/index.json
+++ b/example/pages/field/index.json
@@ -1,9 +1,9 @@
{
"navigationBarTitleText": "Field 输入框",
"usingComponents": {
- "van-button": "../../dist/button/index",
- "van-cell-group": "../../dist/cell-group/index",
+ "demo-block": "../../components/demo-block/index",
"van-field": "../../dist/field/index",
- "van-panel": "../../dist/panel/index"
+ "van-button": "../../dist/button/index",
+ "van-cell-group": "../../dist/cell-group/index"
}
}
diff --git a/example/pages/field/index.wxml b/example/pages/field/index.wxml
index 9586eb80..26fd4aaa 100644
--- a/example/pages/field/index.wxml
+++ b/example/pages/field/index.wxml
@@ -1,90 +1,88 @@
-
-
+
+
+
+
+
+
+
-
+ value="{{ username }}"
+ label="用户名"
+ placeholder="请输入用户名"
+ clearable
+ icon="question"
+ icon-class="icon"
+ required
+ bind:tap-icon="onTapIcon"
+ />
-
+ value="{{ password }}"
+ type="password"
+ label="密码"
+ placeholder="请输入密码"
+ required
+ border="{{ false }}"
+ />
+
+
+
+
+
-
+ value="输入框已禁用"
+ label="用户名"
+ left-icon="contact"
+ disabled
+ border="{{ false }}"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 发送验证码
-
-
-清除输入
-
-
-
-
-
-
-
-清除输入
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/example/pages/field/index.wxss b/example/pages/field/index.wxss
index 003aabb7..ddfc7c9f 100644
--- a/example/pages/field/index.wxss
+++ b/example/pages/field/index.wxss
@@ -1,17 +1,7 @@
-.field__title--radius {
- padding-bottom: 10px;
+.button {
+ vertical-align: middle;
}
-.popup-field-example--bottom {
- width: 100%;
- height: 150px;
-}
-
-.picker-view-example {
- height: 120px;
-}
-
-.picker-view-column-example {
- line-height: 50px;
- text-align: center;
+.icon {
+ color: #38f;
}
diff --git a/packages/card/README.md b/packages/card/README.md
index 729bcc97..2df38f23 100644
--- a/packages/card/README.md
+++ b/packages/card/README.md
@@ -58,9 +58,9 @@
| 名称 | 说明 |
|-----------|-----------|
-| title | 自定义标题栏,如果设置了`title`或`price`属性,则不生效 |
-| desc | 自定义描述栏,如果设置了`desc`或`num`属性,则不生效 |
-| thumb | 自定义 thumb,如果设置了`thumb`属性,则不生效 |
+| title | 自定义标题栏,如果设置了`title`或`price`属性则不生效 |
+| desc | 自定义描述栏,如果设置了`desc`或`num`属性则不生效 |
+| thumb | 自定义 thumb,如果设置了`thumb`属性则不生效 |
| footer | 自定义 footer |
| tags | 自定义 tags |
diff --git a/packages/cell/index.pcss b/packages/cell/index.pcss
index 44b9358b..0f6a6f26 100644
--- a/packages/cell/index.pcss
+++ b/packages/cell/index.pcss
@@ -10,7 +10,6 @@
background-color: $white;
color: $text-color;
font-size: 14px;
- overflow: hidden;
&::after {
left: 15px;
diff --git a/packages/field/README.md b/packages/field/README.md
index d0142d6e..3d4814df 100644
--- a/packages/field/README.md
+++ b/packages/field/README.md
@@ -3,115 +3,171 @@
### 使用指南
在 index.json 中引入组件
```json
-{
- "usingComponents": {
- "van-field": "path/to/vant-weapp/dist/field/index"
- }
+"usingComponents": {
+ "van-field": "path/to/vant-weapp/dist/field/index"
}
```
### 代码演示
#### 基础用法
-field 支持多种展示方式,在 `data` 中传入对应的设置即可。
-```html
-
-
-```
-```js
-Page({
- data: {
- field: {
- focus: true,
- title: '收货人',
- placeholder: '名字',
- value: 'test'
- }
- }
-});
-```
-
-#### Field 列表
```html
-
-
+
```
-#### 监听事件
-
-field会触发一些事件,当你需要监听这些事件时,可以绑定对应的事件。
+#### 自定义类型
+根据`type`属性定义不同类型的输入框
```html
-
-
+
+
+
+
+
```
-```js
-Page(extend({}, {
- data: {
- field: {
- focus: true,
- title: '收货人',
- placeholder: '名字',
- value: 'test'
- }
- },
+#### 禁用输入框
- methods: {
- handleFieldChange(event) {
- console.log(event);
- },
+```html
+
+
+
+```
- handleFieldFocus(event) {
- console.log(event);
- },
+#### 错误提示
+通过`error`或者`error-message`属性增加对应的错误提示
- handleFieldBlur(event) {
- console.log(event);
- }
- }
-}));
+```html
+
+
+
+
+```
+
+#### 高度自适应
+对于 textarea,可以通过`autosize`属性设置高度自适应
+
+```html
+
+
+
+```
+
+#### 插入按钮
+通过 button slot 可以在输入框尾部插入按钮
+
+```html
+
+
+ 发送验证码
+
+
```
### API
-| 参数 | 说明 | 类型 | 默认值 | 必须 |
+| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|-------------|
-| title | 输入框左侧标题,若传入为空,则不显示标题 | String | - | |
-| name | 输入框的名字,作为 form 表单提交时数据的 key | String | componentId 指定的值 | |
-| value | 输入框的内容 | String | - | |
-| type | 输入框的类型,可选值为 input, textarea | String | input | |
-| inputType | 输入框为 input 情况下,输入框的类型,例如:number, text, password | String | text | |
-| placeholder | 输入框为空时占位符 | String | | |
-| maxlength | 最大输入长度,设置为 -1 的时候不限制最大长度 | Number | 140 | |
-| focus | 自动聚焦,拉起键盘 | Boolean | false | |
-| disabled | 输入框是否禁用 | Boolean | false | |
-| mode | 输入框展示样式,可选值为 wrapped, normal | String | normal | |
-| right | 输入框内容是否居右显示 | Boolean | false | |
-| error | 是否显示为输入框错误情况下的样式 | Boolean | false | |
-| componentId | 用于区分输入框之间的唯一名称 | String | - | |
+| label | 输入框左侧文本 | `String` | - |
+| value | 当前输入的值 | `String | Number` | - |
+| type | 可设置为任意原生类型, 如 `number` `idcard` `textarea` `digit` | `String` | `text` |
+| focus | 获取焦点 | `Boolean` | `false` |
+| border | 是否显示内边框 | `Boolean` | `true` |
+| disabled | 是否禁用输入框 | `Boolean` | `false` |
+| readonly | 是否只读 | `Boolean` | `false` |
+| clearable | 是否启用清除控件 | `Boolean` | `false` |
+| required | 是否显示表单必填星号 | `Boolean` | `false` |
+| maxlength | 最大输入长度,设置为 -1 的时候不限制最大长度 | `Number` | `-1` |
+| placeholder | 输入框为空时占位符 | `String` | - |
+| is-link | 是否展示右侧箭头并开启点击反馈 | `Boolean` | `false` |
+| error | 是否将输入内容标红 | `Boolean` | `false` |
+| error-message | 底部错误提示文案,为空时不展示 | `String` | `''` |
+| label-align | 文本对齐方式,可选值为 `center` `right` | `String` | `left` |
+| input-align | 输入框内容对齐方式,可选值为 `center` `right` | `String` | `left` |
+| autosize | 自适应内容高度,只对 textarea 有效 | `Boolean` | `false` |
+| icon | 输入框尾部图标 (可选值见 Icon 组件) | `String` | - |
+| left-icon | 输入框左侧图标 (可选值见 Icon 组件) | `String` | - |
+| cursor-spacing | 输入框聚焦时底部与键盘的距离 | `Number` | `50` |
+| use-button-slot | 是否使用 button slot | `Boolean` | `false` |
### Event
-| 事件名称 | 说明 | 回调参数 |
+| 事件 | 说明 | 回调参数 |
|-----------|-----------|-----------|
-| change | 当绑定值变化时触发的事件 | event对象 |
-| focus | 输入框focus | event对象 |
-| blur | 输入框blur | event对象 |
+| inout | 输入内容时触发 | value: 当前输入值 |
+| change | 输入内容时触发 | value: 当前输入值 |
+| click-icon | 点击尾部图标时触发 | - |
+| focus | 输入框聚焦时触发 | - |
+| blur | 输入框失焦时触发 | - |
+
+### Slot
+
+| 名称 | 说明 |
+|-----------|-----------|
+| label | 自定义输入框标签,如果设置了`label`属性则不生效 |
+| icon | 自定义输入框尾部图标,如果设置了`icon`属性则不生效 |
+| button | 自定义输入框尾部按钮,需要设置`use-button-slot`属性 |
+
+### 外部样式类
+
+| 类名 | 说明 |
+|-----------|-----------|
+| custom-class | 根节点样式类 |
+| input-class | 输入框样式类 |
+| icon-class | 右侧图标样式类 |
+| placeholder-class | 占位内容样式类 |
diff --git a/packages/field/index.js b/packages/field/index.js
index 05df865c..58ca456b 100644
--- a/packages/field/index.js
+++ b/packages/field/index.js
@@ -1,68 +1,117 @@
Component({
behaviors: ['wx://form-field'],
- externalClasses: ['field-class'],
+ externalClasses: [
+ 'custom-class',
+ 'input-class'
+ ],
- relations: {
- '../cell-group/index': {
- type: 'parent'
- }
+ options: {
+ multipleSlots: true
},
properties: {
- title: String,
- type: {
- type: String,
- value: 'input'
- },
- disabled: Boolean,
- focus: Boolean,
- inputType: {
- type: String,
- value: 'text'
- },
- placeholder: String,
- mode: {
- type: String,
- value: 'normal'
- },
- right: Boolean,
+ icon: String,
+ label: String,
error: Boolean,
+ focus: Boolean,
+ center: Boolean,
+ isLink: Boolean,
+ leftIcon: String,
+ disabled: Boolean,
+ autosize: Boolean,
+ readonly: Boolean,
+ required: Boolean,
+ iconClass: String,
+ clearable: Boolean,
+ labelAlign: String,
+ inputAlign: String,
+ errorMessage: String,
+ placeholder: String,
+ useButtonSlot: Boolean,
+ placeholderClass: String,
+ cursorSpacing: {
+ type: Number,
+ value: 50
+ },
maxlength: {
type: Number,
- value: 140
+ value: -1
+ },
+ value: {
+ type: null,
+ value: ''
+ },
+ type: {
+ type: String,
+ value: 'text',
+ observer(currentValue) {
+ this.setData({ currentValue });
+ }
+ },
+ border: {
+ type: Boolean,
+ value: true
}
},
data: {
- showBorder: true
+ focused: false,
+ showClear: false,
+ currentValue: ''
+ },
+
+ attached() {
+ this.setData({
+ currentValue: this.data.value
+ });
},
methods: {
- handleFieldChange(event) {
- const { detail = {} } = event;
- const { value = '' } = detail;
- this.setData({ value });
-
- this.triggerEvent('change', event);
- },
-
- handleFieldFocus(event) {
- this.triggerEvent('focus', event);
- },
-
- handleFieldBlur(event) {
- this.triggerEvent('blur', event);
- },
-
- updateIsLastElement(isLastField) {
- let showBorder = true;
- if (isLastField && this.data.mode === 'normal') {
- showBorder = false;
- }
-
+ onInput(event) {
+ const { value = '' } = event.detail || {};
+ this.triggerEvent('input', value);
+ this.triggerEvent('change', value);
this.setData({
- showBorder
+ currentValue: value,
+ showClear: this.getShowClear({ value })
+ });
+ },
+
+ onFocus(event) {
+ this.triggerEvent('focus', event);
+ this.setData({
+ focused: true,
+ showClear: this.getShowClear({ focused: true })
+ });
+ },
+
+ onBlur(event) {
+ this.focused = false;
+ this.triggerEvent('blur', event);
+ this.setData({
+ focused: false,
+ showClear: this.getShowClear({ focused: false })
+ });
+ },
+
+ onTapIcon() {
+ this.triggerEvent('tap-icon');
+ },
+
+ getShowClear(options) {
+ const {
+ focused = this.data.focused,
+ value = this.data.currentValue
+ } = options;
+
+ return this.data.clearable && focused && value !== '' && !this.data.readonly;
+ },
+
+ onClear() {
+ this.setData({
+ currentValue: '',
+ showClear: this.getShowClear({ value: '' })
});
}
}
diff --git a/packages/field/index.json b/packages/field/index.json
index 114b55d6..8809c46b 100644
--- a/packages/field/index.json
+++ b/packages/field/index.json
@@ -1,6 +1,7 @@
{
"component": true,
"usingComponents": {
- "van-cell": "../cell/index"
+ "van-cell": "../cell/index",
+ "van-icon": "../icon/index"
}
}
\ No newline at end of file
diff --git a/packages/field/index.pcss b/packages/field/index.pcss
index 9a8ec253..a411d0be 100644
--- a/packages/field/index.pcss
+++ b/packages/field/index.pcss
@@ -1,70 +1,88 @@
-@import "../common/_mixins";
+@import '../helper/index.pcss';
.van-field {
- display: block;
- position: relative;
- color: #333;
-}
+ &__body {
+ display: flex;
+ align-items: center;
-.van-field::after {
- @mixin hairline;
- border-bottom-width: 1px;
- left: 15px;
- right: 0;
-}
+ &--textarea {
+ min-height: 24px;
+ }
+ }
-.van-field--no-border::after {
- border-bottom-width: 0;
-}
+ &__control {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ resize: none;
+ display: block;
+ text-align: left;
+ box-sizing: border-box;
+ line-height: inherit;
+ background-color: transparent;
-.van-cell--field {
- padding: 7px 15px;
-}
+ &--disabled {
+ opacity: 1;
+ color: $gray-darker;
+ background-color: transparent;
+ }
-.van-field--wrapped {
- margin: 10px 15px;
- background-color: #fff;
+ &--center {
+ text-align: center;
+ }
- &::after {
- left: 0;
- border-width: 1px;
- border-radius: 4px;
+ &--right {
+ text-align: right;
+ }
+ }
+
+ &__clear,
+ &__icon-container,
+ &__button {
+ flex-shrink: 0;
+ }
+
+ &__clear,
+ &__icon-container {
+ padding: 0 10px;
+ color: $gray-dark;
+ line-height: inherit;
+ margin-right: -10px;
+ vertical-align: middle;
+ }
+
+ &__icon {
+ display: block;
+ font-size: 16px;
+ line-height: inherit;
+ }
+
+ &__button {
+ padding-left: 10px;
+ }
+
+ &__error-message {
+ color: $red;
+ font-size: 12px;
+ text-align: left;
+ }
+
+ &--error {
+ color: $red;
+ }
+
+ &--label {
+ &-center {
+ .van-cell__title {
+ text-align: center;
+ }
+ }
+
+ &-right {
+ .van-cell__title {
+ text-align: right;
+ }
+ }
}
}
-
-/* 圆角输入框,强制展示边框 */
-.van-field--wrapped::after {
- display: block;
-}
-
-.van-field--error {
- color: #f40;
-}
-
-/* 圆角输入框出现错误时,将边框也置红 */
-.van-field--wrapped.van-field--error::after {
- border-color: #f40;
-}
-
-.van-field__title {
- color: #333;
- min-width: 65px;
- padding-right: 10px;
-}
-
-.van-field__input {
- flex: 1;
- line-height: 1.6;
- padding: 4px 0;
- min-height: 22px;
- height: auto;
- font-size: 14px;
-}
-
-.van-field__placeholder {
- font-size: 14px;
-}
-
-.van-field__input--right {
- text-align: right;
-}
diff --git a/packages/field/index.wxml b/packages/field/index.wxml
index 9792e9c9..ab4ab9ec 100644
--- a/packages/field/index.wxml
+++ b/packages/field/index.wxml
@@ -1,39 +1,66 @@
-
- {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
-
-