[breaking change] Cell: rewrite

This commit is contained in:
陈嘉涵 2018-07-31 15:30:26 +08:00
parent 3f0b3dd289
commit 6b8e859825
12 changed files with 255 additions and 310 deletions

View File

@ -1,10 +1,10 @@
{
"navigationBarTitleText": "Cell 单元格",
"usingComponents": {
"demo-block": "../../components/demo-block/index",
"van-cell": "../../dist/cell/index",
"van-icon": "../../dist/icon/index",
"van-badge": "../../dist/badge/index",
"van-panel": "../../dist/panel/index",
"van-tag": "../../dist/tag/index",
"van-cell-group": "../../dist/cell-group/index"
}
}

View File

@ -1,64 +1,35 @@
<van-cell-group border class="cell-panel-demo">
<van-cell title="单行列表" bindtap="handleTap"></van-cell>
</van-cell-group>
<van-cell-group border class="cell-panel-demo">
<van-cell title="单行列表" value="详细信息"></van-cell>
</van-cell-group>
<van-cell-group border class="cell-panel-demo">
<van-cell title="单行列表" label="附加描述" value="详细信息"></van-cell>
</van-cell-group>
<van-panel class="cell-panel-demo" title="带 icon 的 cell">
<van-cell title="单行列表" value="详细信息">
<van-icon slot="icon" type="checked"></van-icon>
</van-cell>
</van-panel>
<van-panel class="cell-panel-demo">
<van-cell title="单行列表">
<picker mode="date" value="{{date}}" start="2018-07-01" end="2018-09-01" bindchange="bindDateChange">
<view class="picker">
选择日期: {{date}}
</view>
</picker>
</van-cell>
</van-panel>
<van-panel class="cell-panel-demo" title="带箭头的 cell">
<van-cell title="只显示箭头" is-link></van-cell>
</van-panel>
<van-cell-group border class="cell-panel-demo">
<van-cell
title="跳转到首页"
is-link
url="/pages/dashboard/index"
bindtap="handleTap"
></van-cell>
</van-cell-group>
<van-panel class="cell-panel-demo" title="cell 组">
<demo-block title="基础用法">
<van-cell-group>
<van-cell title="只显示箭头" is-link></van-cell>
<van-cell title="跳转到首页" is-link url="/pages/dashboard/index"></van-cell>
<van-cell
is-link
only-tap-footer
url="/pages/dashboard/index"
title="只有 footer 点击有效"
bindtap="handleTap"
></van-cell>
<block wx:if="{{ show }}">
<van-cell no-border title="单行列表" label="附加描述" value="不想有 border"></van-cell>
<van-cell title="表单">
<input slot="footer" type="digit" placeholder="带小数点的数字键盘"/>
</van-cell>
</block>
<van-cell title="开关">
<switch slot="footer" checked/>
<van-cell title="单元格" value="内容" />
<van-cell title="单元格" value="内容" label="描述信息" border="{{ false }}" />
</van-cell-group>
</demo-block>
<demo-block title="展示图标">
<van-cell-group>
<van-cell title="单元格" icon="location" border="{{ false }}" />
</van-cell-group>
</demo-block>
<demo-block title="展示箭头">
<van-cell-group>
<van-cell title="单元格" is-link />
<van-cell title="单元格" is-link value="内容" />
<van-cell title="单元格" is-link arrow-direction="down" value="内容" border="{{ false }}" />
</van-cell-group>
</demo-block>
<demo-block title="高级用法">
<van-cell-group>
<van-cell value="内容" icon="shop" is-link>
<view slot="title">
<view class="title">单元格</view>
<van-tag type="danger">标签</van-tag>
</view>
</van-cell>
<van-cell title="单元格" icon="location" is-link />
<van-cell title="单元格" border="{{ false }}">
<van-icon slot="right-icon" name="search" />
</van-cell>
</van-cell-group>
</van-panel>
</demo-block>

View File

@ -1,4 +1,5 @@
.cell-panel-demo {
display: block;
margin-top: 15px;
}
.title {
margin-right: 5px;
display: inline-block;
vertical-align: middle;
}

View File

@ -1,5 +1,5 @@
Component({
props: {
properties: {
border: {
type: Boolean,
value: true

View File

@ -0,0 +1 @@
@import '../helper/index.pcss';

View File

@ -1,3 +1,3 @@
<div class="van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<view class="van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</div>
</view>

View File

@ -2,77 +2,110 @@
### 使用指南
#### 单个 cell 使用示例
在 index.json 中引入组件
```json
{
"usingComponents": {
"van-cell": "path/to/vant-weapp/dist/cell/index",
}
}
"usingComponents": {
"van-cell": "path/to/vant-weapp/dist/cell/index",
"van-cell-group": "path/to/vant-weapp/dist/cell-group/index"
}
```
```wxml
<van-cell title="单行列表" label="附加描述" value="详细信息"></van-cell>
```
### 代码演示
### 属性与事件
#### 基础用法
| 名称 | 类型 | 是否必须 | 默认 | 描述 |
| ------------- | ----------- | -------- | ----- | -------------------------------------------------------------------------------------------------------- |
| title | String | 否 | 无 | 左侧标题 |
| label | Boolean | 否 | false | 标题下方的描述信息 |
| value | String | 否 | 取消 | 右侧内容 |
| noBorder | Boolean | 否 | false | 不显示下边线 |
| isLink | Boolean | 否 | false | 是否展示右侧箭头并开启尝试以 url 跳转 |
| url | String | 否 | - | 当 isLink 设置为 true 时,点击 cell 会尝试跳转到该路径 |
| linkType | String | 否 | navigateTo | 链接跳转类型,可选值为 `navigateTo``redirectTo``switchTab``reLaunch` |
| onlyTapFooter | Boolean | 否 | false | 只有点击 footer 区域才触发 tab 事件 |
| bindtap | EventHandle | 否 | 无 | 点击 cell 时触发,`onlyTapFooter``true` 时点击 footer 区域触发 |
`van-cell-group`组件看成一个容器即可
### 可用的 slot
| 名称 | 是否必须 | 默认 | 描述 |
| ------------- | ----------- | ---- | --------------------------------------------------------------------- |
| 默认 | 否 | 无 | 左侧除了 `title``label` 外的自定义 wxml 内容 |
| icon | 否 | 无 | 标题前自定义的 icon可使用 `icon` 自定义组件,具体使用参考 icon 组件 |
| footer | 否 | 无 | 右侧自定义 wxml 内容,如果设置了 `value` 属性,则不生效 |
### 外部样式类
| 类名 | 说明 |
|-----------|-----------|
| cell-class | 根节点自定义样式类,通过这个可以改变根节点上的样式 |
| title-class | title区域自定义样式 |
#### cell 组使用示例
多个 cell 组件必须作为 `cell-group` 组件的子组件,否则可能出现显示问题。
```json
{
"usingComponents": {
"van-cell": "path/to/vant-weapp/dist/cell/index",
"van-cell-group": "path/to/vant-weapp/dist/cell-group/index"
}
}
```
`cell-group`提供`title-width`控制组内整体 cell 的 title 区域宽度
```wxml
<van-cell-group border title-width="90">
<van-cell title="只显示箭头" is-link></van-cell>
<van-cell title="跳转到首页" is-link url="/pages/dashboard/index"></van-cell>
<van-cell title="单行列表" label="附加描述" value="详细信息"></van-cell>
<van-cell title="表单">
<input slot="footer" type="digit" placeholder="带小数点的数字键盘"/>
</van-cell>
<van-cell title="开关">
<switch slot="footer" checked/>
</van-cell>
```html
<van-cell-group>
<van-cell title="单元格" value="内容" />
<van-cell title="单元格" value="内容" label="描述信息" />
</van-cell-group>
```
### 属性与事件
#### 只设置value
只设置`value`时会向左对齐
| 名称 | 类型 | 是否必须 | 默认 | 描述 |
| ---------- | ------- | -------- | ----- | ---------------- |
| titleWidth | Number | 否 | 无 | title宽度 |
| border | Boolean | 否 | false | 是否显示上下边框 |
```html
<van-cell-group>
<van-cell value="内容" />
</van-cell-group>
```
#### 展示图标
通过`icon`属性在标题左侧展示图标
```html
<van-cell-group>
<van-cell title="单元格" icon="location" />
</van-cell-group>
```
#### 展示箭头
传入`is-link`属性则会在右侧显示箭头,并且可以通过传入`arrow-direction`属性控制箭头方向
```html
<van-cell-group>
<van-cell title="单元格" is-link />
<van-cell title="单元格" is-link value="内容" />
<van-cell title="单元格" is-link arrow-direction="down" value="内容" />
</van-cell-group>
```
#### 高级用法
如以上用法不能满足你的需求,可以使用对应的`slot`来自定义显示的内容
```html
<van-cell-group>
<van-cell value="内容" icon="shop" is-link>
<template slot="title">
<span class="van-cell-text">单元格</span>
<van-tag type="danger">标签</van-tag>
</template>
</van-cell>
<van-cell title="单元格" icon="location" is-link />
<van-cell title="单元格">
<van-icon slot="right-icon" name="search" class="van-cell__right-icon" />
</van-cell>
</van-cell-group>
```
### CellGroup API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| border | 是否显示外边框 | `Boolean` | `true` |
### Cell API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| icon | 左侧图标,可选值见 Icon 组件 | `String` | - |
| title | 左侧标题 | `String | Number` | - |
| value | 右侧内容 | `String | Number` | - |
| label | 标题下方的描述信息 | `String` | - |
| border | 是否显示内边框 | `Boolean` | `true` |
| center | 是否使内容垂直居中 | `Boolean` | `false` |
| url | 跳转链接 | `String` | - |
| to | 路由跳转对象,同 `vue-router` 的 to | `String | Object` | - |
| replace | 跳转时是否替换当前 history | `String` | `false` |
| clickable | 是否开启点击反馈 | `Boolean` | `false` |
| is-link | 是否展示右侧箭头并开启点击反馈 | `Boolean` | `false` |
| required | 是否显示表单必填星号 | `Boolean` | `false` |
| arrow-direction | 箭头方向,可选值为 `left` `up` `down` | `String` | - |
### Cell Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 点击 cell 时触发 | - |
### Cell Slot
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义显示内容 |
| icon | 自定义`icon` |
| title | 自定义`title` |
| right-icon | 自定义右侧按钮,默认是`arrow` |

View File

@ -1,105 +1,38 @@
const warn = (msg, getValue) => {
console.warn(msg);
console.log('接受到的值为:', getValue);
};
Component({
externalClasses: ['cell-class', 'title-class'],
options: {
multipleSlots: true
},
relations: {
'../cell-group/index': {
type: 'parent'
properties: {
title: null,
value: null,
icon: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
arrowDirection: String,
border: {
type: Boolean,
value: true
}
},
properties: {
title: {
type: String,
description: '左侧标题'
},
label: {
type: String,
description: '标题下方的描述信息'
},
value: {
type: String,
description: '右侧内容'
},
onlyTapFooter: {
type: Boolean,
description: '只有点击 footer 区域才触发 tab 事件'
},
isLink: {
type: null,
value: '',
description: '是否展示右侧箭头并开启尝试以 url 跳转'
},
linkType: {
type: String,
value: 'navigateTo',
description: '链接类型,可选值为 navigateToredirectToswitchTabreLaunch'
},
url: {
type: String,
value: ''
},
noBorder: Boolean
},
data: {
isLastCell: true,
titleWidth: 'auto'
},
methods: {
footerTap() {
// 如果并没有设置只点击 footer 生效那就不需要额外处理。cell 上有事件会自动处理
if (!this.data.onlyTapFooter) {
return;
}
this.triggerEvent('tap', {});
doNavigate.call(this);
onTap() {
this.triggerEvent('tap');
this.navigate();
},
cellTap() {
// 如果只点击 footer 生效,那就不需要在 cell 根节点上处理
if (this.data.onlyTapFooter) {
return;
}
navigate() {
const { url = '' } = this.data;
this.triggerEvent('tap', {});
doNavigate.call(this);
},
if (!this.data.isLink || !url || url === 'true' || url === 'false') return;
// 用于被 cell-group 更新,标志是否是最后一个 cell
updateIsLastElement(isLastCell) {
this.setData({ isLastCell });
},
// 设置统一的title区域宽度
setTitleWidth(titleWidth) {
this.setData({
titleWidth: `${titleWidth}px`
});
wx[this.data.linkType].call(wx, { url });
}
}
});
// 处理跳转
function doNavigate() {
const { url = '' } = this.data;
const type = typeof this.data.isLink;
if (!this.data.isLink || !url || url === 'true' || url === 'false') return;
if (type !== 'boolean' && type !== 'string') {
warn('isLink 属性值必须是一个字符串或布尔值', this.data.isLink);
return;
}
if (['navigateTo', 'redirectTo', 'switchTab', 'reLaunch'].indexOf(this.data.linkType) === -1) {
warn('linkType 属性可选值为 navigateToredirectToswitchTabreLaunch', this.data.linkType);
return;
}
wx[this.data.linkType].call(wx, { url });
}

View File

@ -1,3 +1,6 @@
{
"component": true
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}

View File

@ -1,98 +1,94 @@
@import "../common/_mixins";
@import '../helper/index.pcss';
:host:last-child {
background-color: red;
}
.van-cell {
position: relative;
padding: 12px 15px;
width: 100%;
display: flex;
align-items: center;
line-height: 1.4;
background-color: #fff;
padding: 10px 15px;
box-sizing: border-box;
line-height: 24px;
position: relative;
background-color: $white;
color: $text-color;
font-size: 14px;
overflow: hidden;
&::after {
@mixin hairline;
border-bottom-width: 1px;
left: 15px;
right: 0;
width: auto;
transform: scale(1, .5);
border-bottom-width: 1px;
}
&__icon {
margin-right: 5px;
&:empty {
display: none
}
&-group {
background-color: $white;
}
&__title {
padding-right: 10px;
&:empty {
display: none;
}
&__label {
font-size: 12px;
line-height: 1.2;
color: $gray-darker;
}
&__bd {
&__title,
&__value {
flex: 1;
}
&__text {
line-height: 24px;
font-size: 14px;
}
&__desc {
line-height: 1.2;
font-size: 12px;
color: #666;
}
&__ft {
position: relative;
&__value {
overflow: hidden;
text-align: right;
color: #666;
vertical-align: middle;
}
&__no-pading{
padding: 0;
&__left-icon {
font-size: 16px;
line-height: 24px;
margin-right: 5px;
}
.van-cell__bd_padding {
padding: 12px 0 12px 15px;
&__right-icon {
color: $gray-dark;
font-size: 12px;
line-height: 24px;
margin-left: 5px;
.van-form__input{
height: 26px;
}
&--left::before {
transform: rotate(180deg);
}
.van-cell__ft_padding {
padding: 12px 15px 12px 0;
&--up::before {
transform: rotate(-90deg);
}
&--down::before {
transform: rotate(90deg);
}
}
&.last-cell::after, &.no-border::after {
display: none;
&--clickable {
&:active {
background-color: $active-color;
}
}
}
&--required {
overflow: visible;
&::before {
content: '*';
position: absolute;
left: 7px;
font-size: 14px;
color: $red;
}
}
.van-cell--access .van-cell__ft {
padding-right: 13px;
}
.van-cell--access .van-cell__ft::after {
position: absolute;
top: 50%;
right: 2px;
content: " ";
display: inline-block;
height: 6px;
width: 6px;
border-width: 2px 2px 0 0;
border-color: #c8c8c8;
border-style: solid;
transform: translateY(-50%) matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
}
.van-cell--switch {
padding-top: 6px;
padding-bottom: 6px;
&--center {
align-items: center;
}
}

View File

@ -1,25 +1,31 @@
<view
catchtap="cellTap"
class="cell-class van-cell {{ isLastCell ? 'last-cell' : '' }} {{ isLink ? 'van-cell--access' : '' }} {{ noBorder ? 'no-border' : ''}}"
<div
class="van-cell {{ center ? 'van-cell--center' : '' }} {{ required ? 'van-cell--required' : '' }} {{ isLink || clickable ? 'van-cell--clickable' : '' }} {{ border ? 'van-hairline' : '' }}"
bind:tap="onTap"
>
<van-icon wx:if="icon" custom-class="van-cell__left-icon" name="{{ icon }}" />
<slot wx:else name="icon" />
<view class="van-cell__icon">
<slot name="icon"></slot>
<view wx:if="{{ title }}" class="van-cell__title">
<view>{{ title }}</view>
<view wx:if="{{ label }}" class="van-cell__label">{{ label }}</view>
</view>
<view wx:else class="van-cell__title">
<slot name="title" />
</view>
<view class="title-class van-cell__title" style="width: {{ titleWidth }}">
<view wx:if="{{ title }}" class="van-cell__text">{{ title }}</view>
<view wx:if="{{ label }}" class="van-cell__desc">{{ label }}</view>
<view wx:if="{{ value }}" class="van-cell__value">
<view>{{ value }}</view>
</view>
<view wx:else>
<slot />
</view>
<view class="van-cell__bd">
<slot></slot>
</view>
<van-icon
wx:if="{{ isLink }}"
name="arrow"
custom-class="van-cell__right-icon {{ arrowDirection ? 'van-cell__right-icon--' + arrowDirection : '' }}"
/>
<slot wx:else name="right-icon" />
<view bindtap="footerTap" class="van-cell__ft">
<block wx:if="{{value}}">{{ value }}</block>
<block wx:else>
<slot name="footer"></slot>
</block>
</view>
</view>
<slot name="extra" />
</div>

View File

@ -1,5 +1,6 @@
@import "../mixins/border-retina.pcss";
.van-hairline,
.van-hairline--top,
.van-hairline--left,
.van-hairline--right,
@ -17,7 +18,7 @@
&--top::after {
border-top-width: 1px;
}
z
&--left::after {
border-left-width: 1px;
}