diff --git a/example/app.json b/example/app.json index 597ab3a9..950b8d9f 100644 --- a/example/app.json +++ b/example/app.json @@ -55,7 +55,8 @@ "pages/collapse/index", "pages/picker/index", "pages/overlay/index", - "pages/circle/index" + "pages/circle/index", + "pages/grid/index" ], "window": { "navigationBarBackgroundColor": "#f8f8f8", @@ -115,7 +116,9 @@ "van-collapse-item": "./dist/collapse-item/index", "van-picker": "./dist/picker/index", "van-overlay": "./dist/overlay/index", - "van-circle": "./dist/circle/index" + "van-circle": "./dist/circle/index", + "van-grid": "./dist/grid/index", + "van-grid-item": "./dist/grid-item/index" }, "sitemapLocation": "sitemap.json" } diff --git a/example/config.js b/example/config.js index 2d65425f..d5d6ac9b 100644 --- a/example/config.js +++ b/example/config.js @@ -155,6 +155,10 @@ export default [ groupName: '导航组件', icon: 'https://img.yzcdn.cn/vant/nav-0401.svg', list: [ + { + path: '/grid', + title: 'Grid 宫格' + }, { path: '/sidebar', title: 'Sidebar 侧边导航' diff --git a/example/pages/grid/index.js b/example/pages/grid/index.js new file mode 100644 index 00000000..cc11dfda --- /dev/null +++ b/example/pages/grid/index.js @@ -0,0 +1,3 @@ +import Page from '../../common/page'; + +Page(); diff --git a/example/pages/grid/index.json b/example/pages/grid/index.json new file mode 100644 index 00000000..832f0c7d --- /dev/null +++ b/example/pages/grid/index.json @@ -0,0 +1,3 @@ +{ + "navigationBarTitleText": "Grid 宫格" +} diff --git a/example/pages/grid/index.wxml b/example/pages/grid/index.wxml new file mode 100644 index 00000000..1d1f7822 --- /dev/null +++ b/example/pages/grid/index.wxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/pages/grid/index.wxss b/example/pages/grid/index.wxss new file mode 100644 index 00000000..ed765f40 --- /dev/null +++ b/example/pages/grid/index.wxss @@ -0,0 +1,4 @@ +.van-image { + width: 100%; + height: 90px; +} diff --git a/packages/common/style/var.less b/packages/common/style/var.less index 74ac4796..2a8249ad 100644 --- a/packages/common/style/var.less +++ b/packages/common/style/var.less @@ -19,6 +19,20 @@ @background-color: #f8f8f8; @background-color-light: #fafafa; +// Padding +@padding-base: 4px; +@padding-xs: @padding-base * 2; +@padding-sm: @padding-base * 3; +@padding-md: @padding-base * 4; +@padding-lg: @padding-base * 6; +@padding-xl: @padding-base * 8; + +// Font Size +@font-size-xs: 10px; +@font-size-sm: 12px; +@font-size-md: 14px; +@font-size-lg: 16px; + // Button @button-default-color: @text-color; @button-default-background-color: @white; @@ -171,3 +185,11 @@ // iPhoneX @safe-area-inset-bottom: 34px; + +// GridItem +@grid-item-content-padding: @padding-md @padding-xs; +@grid-item-content-background-color: @white; +@grid-item-content-active-color: @active-color; +@grid-item-icon-size: 26px; +@grid-item-text-color: @gray-darker; +@grid-item-text-font-size: @font-size-sm; diff --git a/packages/grid-item/index.json b/packages/grid-item/index.json new file mode 100644 index 00000000..0a336c08 --- /dev/null +++ b/packages/grid-item/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index" + } +} diff --git a/packages/grid-item/index.less b/packages/grid-item/index.less new file mode 100644 index 00000000..5d76f3ad --- /dev/null +++ b/packages/grid-item/index.less @@ -0,0 +1,57 @@ +@import '../common/style/var.less'; + +.van-grid-item { + position: relative; + float: left; + box-sizing: border-box; + + &--square { + height: 0; + } + + &__content { + display: flex; + flex-direction: column; + box-sizing: border-box; + height: 100%; + padding: @grid-item-content-padding; + background-color: @grid-item-content-background-color; + + &::after { + z-index: 1; + border-width: 0 1px 1px 0; + } + + &--surround { + &::after { + border-width: 1px; + } + } + + &--center { + align-items: center; + justify-content: center; + } + + &--square { + position: absolute; + top: 0; + right: 0; + left: 0; + } + + &--clickable:active { + background-color: @grid-item-content-active-color; + } + } + + &__icon { + font-size: @grid-item-icon-size; + } + + &__text { + color: @grid-item-text-color; + font-size: @grid-item-text-font-size; + word-break: break-all; + } +} diff --git a/packages/grid-item/index.ts b/packages/grid-item/index.ts new file mode 100644 index 00000000..fdca6489 --- /dev/null +++ b/packages/grid-item/index.ts @@ -0,0 +1,66 @@ +import { link } from '../mixins/link'; +import { VantComponent } from '../common/component'; + +VantComponent({ + relation: { + name: 'grid', + type: 'ancestor', + linked(parent) { + this.parent = parent; + } + }, + + mixins: [link], + + props: { + icon: String, + text: String, + useSlot: Boolean + }, + + mounted() { + this.updateStyle(); + }, + + methods: { + updateStyle() { + if (!this.parent) { + return; + } + + const { data, children } = this.parent; + const { columnNum, border, square, gutter, clickable, center } = data; + const width = `${100 / columnNum}%`; + + const styleWrapper: Array = []; + styleWrapper.push(`width: ${width}`); + + if (square) { + styleWrapper.push(`padding-top: ${width}`); + } + + if (gutter) { + styleWrapper.push(`padding-right: ${gutter}px`); + } + + const index = children.indexOf(this); + if (index >= columnNum) { + styleWrapper.push(`margin-top: ${gutter}px`); + } + + this.setData({ + style: styleWrapper.join('; '), + center, + border, + square, + gutter, + clickable + }); + }, + + onClick() { + this.$emit('click'); + this.jumpLink(); + } + } +}); diff --git a/packages/grid-item/index.wxml b/packages/grid-item/index.wxml new file mode 100644 index 00000000..46d52fdb --- /dev/null +++ b/packages/grid-item/index.wxml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + {{ text }} + + + + + diff --git a/packages/grid/README.md b/packages/grid/README.md new file mode 100644 index 00000000..fbadef7a --- /dev/null +++ b/packages/grid/README.md @@ -0,0 +1,131 @@ +# Grid 宫格 + +### 介绍 + +宫格可以在水平方向上把页面分隔成等宽度的区块,用于展示内容或进行页面导航 + +### 引入 + +在`app.json`或`index.json`中引入组件,默认为`ES6`版本,`ES5`引入方式参见[快速上手](#/quickstart) + +```json +"usingComponents": { + "van-grid": "path/to/vant-weapp/dist/grid/index", + "van-grid-item": "path/to/vant-weapp/dist/grid-item/index" +} +``` + +## 代码演示 + +### 基本用法 + +通过`icon`属性设置格子内的图标,`text`属性设置文字内容 + +```html + + + +``` + +### 自定义列数 + +默认一行展示四个格子,可以通过`column-num`自定义列数 + +```html + + + +``` + +### 自定义内容 + +通过插槽可以自定义格子展示的内容 + +```html + + + + + +``` + +### 正方形格子 + +设置`square`属性后,格子的高度会和宽度保持一致 + +```html + + + +``` + +### 格子间距 + +通过`gutter`属性设置格子之间的距离 + +```html + + + +``` + +### 页面跳转 + +可以通过`url`属性进行页面跳转,通过`link-type`属性控制跳转类型 + +```html + + + + +``` + +## API + +### Grid Props + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| ---------- | ------------------------------ | ------------------ | ------- | ---- | +| column-num | 列数 | *number* | `4` | - | +| gutter | 格子之间的间距,默认单位为`px` | *string \| number* | `0` | - | +| border | 是否显示边框 | *boolean* | `true` | - | +| center | 是否将格子内容居中显示 | *boolean* | `true` | - | +| square | 是否将格子固定为正方形 | *boolean* | `false` | - | +| clickable | 是否开启格子点击反馈 | *boolean* | `false` | - | +| use-slot | 是否使用自定义内容的插槽 | *boolean* | `false` | + +### GridItem Props + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| --------- | ---------------------------------------------------------- | -------- | ------------ | ---- | +| text | 文字 | *string* | - | - | +| icon | 图标名称或图片链接,可选值见 Icon 组件 | *string* | - | - | +| url | 跳转链接 | *string* | - | - | +| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | *string* | `navigateTo` | - | + +### GridItem Events + +| 事件名 | 说明 | 回调参数 | +| ---------- | -------------- | -------- | +| bind:click | 点击格子时触发 | - | + +### GridItem Slots + +| 名称 | 说明 | +| ------- | ---------------------------------------------------- | +| default | 自定义宫格的所有内容,需要设置`use-slot`属性 | +| icon | 自定义图标,如果设置了`use-slot`或者`icon`属性则不生效 | +| text | 自定义文字,如果设置了`use-slot`或者`text`属性则不生效 | diff --git a/packages/grid/index.json b/packages/grid/index.json new file mode 100644 index 00000000..467ce294 --- /dev/null +++ b/packages/grid/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/packages/grid/index.less b/packages/grid/index.less new file mode 100644 index 00000000..3c09d936 --- /dev/null +++ b/packages/grid/index.less @@ -0,0 +1,5 @@ +.van-grid { + position: relative; + box-sizing: border-box; + overflow: hidden; +} diff --git a/packages/grid/index.ts b/packages/grid/index.ts new file mode 100644 index 00000000..ba5d3b19 --- /dev/null +++ b/packages/grid/index.ts @@ -0,0 +1,70 @@ +import { VantComponent } from '../common/component'; + +VantComponent({ + relation: { + name: 'grid-item', + type: 'descendant', + linked(child) { + this.children.push(child); + }, + unlinked(child) { + this.children = this.children.filter( + (item: WechatMiniprogram.Component.TrivialInstance) => item !== child + ); + } + }, + + props: { + square: { + type: Boolean, + observer: 'updateChildren' + }, + gutter: { + type: [Number, String], + value: 0, + observer: 'updateChildren' + }, + clickable: { + type: Boolean, + observer: 'updateChildren' + }, + columnNum: { + type: Number, + value: 4, + observer: 'updateChildren' + }, + center: { + type: Boolean, + value: true, + observer: 'updateChildren' + }, + border: { + type: Boolean, + value: true, + observer: 'updateChildren' + } + }, + + beforeCreate() { + this.children = []; + }, + + created() { + const { gutter } = this.data; + if (gutter) { + this.setData({ + style: `padding-left: ${gutter}px` + }); + } + }, + + methods: { + updateChildren() { + this.children.forEach( + (child: WechatMiniprogram.Component.TrivialInstance) => { + child.updateStyle(); + } + ); + } + } +}); diff --git a/packages/grid/index.wxml b/packages/grid/index.wxml new file mode 100644 index 00000000..fc76cc30 --- /dev/null +++ b/packages/grid/index.wxml @@ -0,0 +1,3 @@ + + +