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 @@
+
+
+