[new feature] add nav-bar component

This commit is contained in:
陈嘉涵 2018-08-11 07:53:37 +08:00
parent 9bfe840047
commit e4941a5346
21 changed files with 246 additions and 323 deletions

View File

@ -16,6 +16,7 @@
- 新增 Loading 组件
- 新增 Panel 组件
- 新增 Popup 组件
- 新增 NavBar 组件
- 新增 NoticeBar 组件
- 新增 Search 组件
- 新增 Steps 组件

View File

@ -23,6 +23,7 @@ const MAP = {
icon: 'icon-201808092138.png',
col: 'layout-201808092138.png',
loading: 'loading-201808092138.png',
'nav-bar': 'nav-bar-201808110751.png',
'notice-bar': 'notice-bar-201808092138.png',
popup: 'popup-201808092138.png',
panel: 'panel-201808092138.png',

View File

@ -65,6 +65,10 @@ module.exports = {
path: '/loading',
title: 'Loading 加载'
},
{
path: '/nav-bar',
title: 'NavBar 导航栏'
},
{
path: '/notice-bar',
title: 'NoticeBar 通告栏'

View File

@ -13,6 +13,7 @@ export default {
'field': () => import('../../packages/field/README.md'),
'icon': () => import('../../packages/icon/README.md'),
'loading': () => import('../../packages/loading/README.md'),
'nav-bar': () => import('../../packages/nav-bar/README.md'),
'notice-bar': () => import('../../packages/notice-bar/README.md'),
'panel': () => import('../../packages/panel/README.md'),
'popup': () => import('../../packages/popup/README.md'),
@ -21,6 +22,5 @@ export default {
'steps': () => import('../../packages/steps/README.md'),
'switch': () => import('../../packages/switch/README.md'),
'tag': () => import('../../packages/tag/README.md'),
'toast': () => import('../../packages/toast/README.md'),
'tree-select': () => import('../../packages/tree-select/README.md')
};

View File

@ -2,14 +2,15 @@
"pages": [
"pages/dashboard/index",
"pages/actionsheet/index",
"pages/button/index",
"pages/badge/index",
"pages/button/index",
"pages/card/index",
"pages/cell/index",
"pages/field/index",
"pages/icon/index",
"pages/layout/index",
"pages/loading/index",
"pages/nav-bar/index",
"pages/notice-bar/index",
"pages/panel/index",
"pages/popup/index",

View File

@ -26,6 +26,10 @@ export default {
name: 'Loading 加载',
path: '/pages/loading/index'
},
{
name: 'NavBar 导航栏',
path: '/pages/nav-bar/index'
},
{
name: 'NoticeBar 通告栏',
path: '/pages/notice-bar/index'

View File

@ -1 +1 @@
Page({})
Page({});

View File

@ -0,0 +1,9 @@
Page({
onTapLeft() {
wx.showToast({ title: '点击返回', icon: 'none' });
},
onTapRight() {
wx.showToast({ title: '点击按钮', icon: 'none' });
}
});

View File

@ -0,0 +1,8 @@
{
"navigationBarTitleText": "NavBar 导航栏",
"usingComponents": {
"demo-block": "../../components/demo-block/index",
"van-icon": "../../dist/icon/index",
"van-nav-bar": "../../dist/nav-bar/index"
}
}

View File

@ -0,0 +1,16 @@
<demo-block title="基础用法">
<van-nav-bar
title="标题"
left-text="返回"
right-text="按钮"
left-arrow
bind:tap-left="onTapLeft"
bind:tap-right="onTapRight"
/>
</demo-block>
<demo-block title="高级用法">
<van-nav-bar title="标题" left-text="返回" left-arrow>
<van-icon name="search" slot="right" custom-class="icon" />
</van-nav-bar>
</demo-block>

View File

@ -0,0 +1,3 @@
.icon {
color: #38f;
}

View File

@ -0,0 +1,79 @@
## NavBar 导航栏
### 使用指南
``` javascript
import { NavBar } from 'vant';
Vue.use(NavBar);
```
### 代码演示
#### 基础用法
```html
<van-nav-bar
title="标题"
left-text="返回"
right-text="按钮"
left-arrow
bind:tap-left="onTapLeft"
bind:tap-right="onTapRight"
/>
```
```js
export default {
methods: {
onTapLeft() {
wx.showToast({ title: '点击返回', icon: 'none' });
},
onTapRight() {
wx.showToast({ title: '点击按钮', icon: 'none' });
}
}
}
```
#### 高级用法
通过 slot 定制内容
```html
<van-nav-bar title="标题" left-text="返回" left-arrow>
<van-icon name="search" slot="right" />
</van-nav-bar>
```
### API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| title | 标题 | `String` | `''` |
| left-text | 左侧文案 | `String` | `''` |
| right-text | 右侧文案 | `String` | `''` |
| left-arrow | 是否显示左侧箭头 | `Boolean` | `false` |
| fixed | 是否固定在顶部 | `Boolean` | `false` |
| z-index | 元素 z-index | `Number` | `1` |
### Slot
| 名称 | 说明 |
|-----------|-----------|
| title | 自定义标题 |
| left | 自定义左侧区域内容 |
| right | 自定义右侧区域内容 |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| tap-left | 点击左侧按钮时触发 | - |
| tap-right | 点击右侧按钮时触发 | - |
### 外部样式类
| 类名 | 说明 |
|-----------|-----------|
| custom-class | 根节点样式类 |
| title-class | 标题样式类 |

32
packages/nav-bar/index.js Normal file
View File

@ -0,0 +1,32 @@
Component({
externalClasses: [
'custom-class',
'title-class'
],
options: {
multipleSlots: true
},
properties: {
title: String,
leftText: String,
rightText: String,
leftArrow: Boolean,
fixed: Boolean,
zIndex: {
type: Number,
value: 1
}
},
methods: {
onTapLeft() {
this.triggerEvent('tap-left');
},
onTapRight() {
this.triggerEvent('tap-right');
}
}
});

View File

@ -0,0 +1,61 @@
@import '../common/style/var.pcss';
.van-nav-bar {
height: 46px;
position: relative;
user-select: none;
text-align: center;
line-height: 46px;
background-color: $white;
&__arrow {
color: $blue;
vertical-align: middle;
transform: rotate(180deg);
+ .van-nav-bar__text {
margin-left: -20px;
padding-left: 25px;
}
}
&--fixed {
top: 0;
left: 0;
width: 100%;
position: fixed;
}
&__title {
margin: 0 auto;
max-width: 60%;
font-size: 16px;
}
&__left,
&__right {
bottom: 0;
font-size: 14px;
position: absolute;
}
&__left {
left: 15px;
}
&__right {
right: 15px;
}
&__text {
color: $blue;
margin: 0 -15px;
padding: 0 15px;
display: inline-block;
vertical-align: middle;
&:active {
background-color: $active-color;
}
}
}

View File

@ -0,0 +1,24 @@
<view
class="custom-class van-nav-bar van-hairline--bottom {{ fixed ? 'van-nav-bar--fixed' : '' }}"
style="z-index: {{ zIndex }}"
>
<view class="van-nav-bar__left" bind:tap="onTapLeft">
<block wx:if="{{ leftArrow || leftText }}">
<van-icon
wx:if="{{ leftArrow }}"
name="arrow"
custom-class="van-nav-bar__arrow"
/>
<view wx:if="{{ leftText }}" class="van-nav-bar__text">{{ leftText }}</view>
</block>
<slot wx:else name="left" />
</view>
<view class="van-nav-bar__title title-class van-ellipsis">
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
</view>
<view class="van-nav-bar__right" bind:tap="onTapRight">
<view wx:if="{{ rightText }}" class="van-nav-bar__text">{{ rightText }}</view>
<slot wx:else name="right" />
</view>
</view>

View File

@ -1,55 +0,0 @@
## Toast 轻提示
### 使用指南
在 json 文件中配置 toast 组件
```json
"usingComponents": {
"van-toast": "/path/to/vant-weapp/dist/toast/index"
}
```
在需要使用的页面里引入组件库模板和脚本
```html
<van-toast id="van-toast-test"></van-toast>
```
```js
const Toast = require('path/to/vant-weapp/dist/toast/toast');
Page({
// ...
// 可以在任意方法里直接调用,即可唤起
handleClick() {
Toast({
message: 'toast me',
selector: '#van-toast-test'
});
}
});
```
#### 加载提示
```js
Toast.loading({
selector: '#van-toast-test'
});
```
### 参数说明
#### 方法
| 方法名 | 参数 | 返回值 | 介绍 |
|-----------|-----------|-----------|-------------|
| Toast | `options`, `timeout` | - | 展示提示 |
| Toast.loading | `options` | - | 展示加载提示 |
| Toast.clear | - | - | 关闭提示 |
| Toast.setDefaultOptions | `options` 格式同 Toast 函数可以传入的参数, `type` 可选 global/page, 分别指定对整个小程序生效/对当前页面生效 | - | 修改默认配置,对所有 Toast 生效 |
| Toast.resetDefaultOptions | `type` 可选 global/page | - | 重置默认配置,对所有 Toast 生效 |
#### options 具体参数如下
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| message | toast 显示文案 | String | - |
| type | 提示类型, 可选值loadingsuccessfail | String | - |
| icon | toast 显示图标,可以用 icon 里面支持的所有图标 | String | - |
| image | toast 显示图标,为图片的链接,传入此值后会覆盖 icon 值 | String | - |
| timeout | toast 显示时间单位为毫秒小于0则会一直显示需要手动调用 Toast.clear 清除 | Number | - |

View File

@ -1,40 +0,0 @@
const DEFAULT_DATA = {
show: false,
message: '',
icon: '',
image: '',
mask: false
};
const SUPPORT_TYPE = ['loading', 'success', 'fail'];
Component({
data: {
...DEFAULT_DATA
},
methods: {
show(options) {
const toastOptions = { ...options };
let icon = options.icon || '';
let image = options.image || '';
if (SUPPORT_TYPE.indexOf(options.type) > -1) {
icon = options.type;
image = '';
}
this.setData({
...toastOptions,
icon,
image
});
},
clear() {
this.setData({
...DEFAULT_DATA
});
}
}
});

View File

@ -1,59 +0,0 @@
.van-toast {
position: fixed;
top: 35%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
background: rgba(0, 0, 0, 0.7);
color: #fff;
font-size: 14px;
line-height: 1.5em;
margin: 0 auto;
box-sizing: border-box;
padding: 10px 18px;
text-align: center;
border-radius: 4px;
z-index: 100;
}
/* 没有文字时,需要调整展示大小 */
.van-toast--notitle {
padding: 18px;
}
.van-toast__icon {
display: block;
width: 40px;
height: 40px;
line-height: 40px;
margin: 0 auto;
padding: 12px 15px;
font-size: 38px;
text-align: center;
}
/* 加载中的状态 */
.van-toast__icon-loading {
line-height: 0;
}
.van-loading {
width:20px;
height:20px;
display: inline-block;
vertical-align: middle;
animation: weuiLoading 1s steps(12, end) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iciIgd2lkdGg9JzEyMHB4JyBoZWlnaHQ9JzEyMHB4JyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiPjwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjRTlFOUU5JwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoMCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICA8L3JlY3Q+CiAgICA8cmVjdCB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nIzk4OTY5NycKICAgICAgICAgIHRyYW5zZm9ybT0ncm90YXRlKDMwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4KICAgICAgICAgICAgICAgICByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyM5Qjk5OUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSg2MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz4KICAgIDwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjQTNBMUEyJwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoOTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNBQkE5QUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxMjAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCMkIyQjInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxNTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCQUI4QjknCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxODAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDMkMwQzEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyMTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDQkNCQ0InCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEMkQyRDInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEQURBREEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNFMkUyRTInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0Pgo8L3N2Zz4=) no-repeat;
background-size: 100%;
}
.van-toast__icon-loading .van-loading {
width: 40px;
height: 40px;
}
/* 自定义图标 */
.van-toast__icon-image {
background-size: 40px;
background-position: center;
background-repeat: no-repeat;
}

View File

@ -1,30 +0,0 @@
<view
class="van-toast {{ !message ? 'van-toast--notitle' : '' }}"
wx:if="{{ show }}"
bindtap="clearZanToast"
>
<!-- icon 展示 -->
<block
wx:if="{{ icon || image }}"
>
<view
wx:if="{{ image }}"
class="van-toast__icon van-toast__icon-image"
style="background-image: url({{ image }});"
></view>
<view
wx:elif="{{ icon === 'loading' }}"
class="van-toast__icon van-toast__icon-loading"
>
<view class="van-loading"></view>
</view>
<van-icon
wx:else
type="{{ icon }}"
class="van-toast__icon"
></van-icon>
</block>
<!-- 文案展示 -->
<view wx:if="{{ message }}">{{ message }}</view>
</view>

View File

@ -1,136 +0,0 @@
const TOAST_CONFIG_KEY = 'vant.__zanToastPageConfig';
const DEFAULT_SHOW_TOAST_TIME = 3000;
let timeoutData = {
timeoutId: 0,
toastCtx: null
};
let globalToastUserConfig = {};
// 获取页面上下文
function getPageCtx(pageCtx) {
let ctx = pageCtx;
if (!ctx) {
const pages = getCurrentPages();
ctx = pages[pages.length - 1];
}
return ctx;
}
// 获取当前页面的 toast 配置数据
function getPageToastConfig(pageCtx) {
const vantData = pageCtx.data.vant || {};
return vantData.__zanToastPageConfig || {};
}
// Toast 显示函数
function Toast(optionsOrMsg, pageCtx) {
// 参数格式化处理
// 如果是文字,默认为 message
let options = optionsOrMsg || {};
if (typeof optionsOrMsg === 'string') {
options = { message: optionsOrMsg };
}
let ctx = getPageCtx(pageCtx);
const pageToastUserSetting = getPageToastConfig(ctx);
const parsedOptions = {
...globalToastUserConfig,
...pageToastUserSetting,
...options
};
const toastCtx = ctx.selectComponent(parsedOptions.selector);
if (!toastCtx) {
console.error('无法找到对应的toast组件请于页面中注册并在 wxml 中声明 toast 自定义组件');
return;
}
if (timeoutData.timeoutId) {
Toast.clear();
}
toastCtx.show({
...parsedOptions,
show: true
});
let timeoutId = 0;
// toast 计时如果小于0就不会去关闭。
// 如果不传,就取默认值
const timeoutOption = parsedOptions.timeout || DEFAULT_SHOW_TOAST_TIME;
if (timeoutOption >= 0) {
timeoutId = setTimeout(() => {
toastCtx.clear();
}, timeoutOption);
}
timeoutData = {
timeoutId,
toastCtx
};
}
// 设置 toast 基础属性
Toast.setDefaultOptions = function (options = {}, type = 'page') {
const parsedDefaultOptions = {
selector: options.selector || '',
type: options.type || '',
icon: options.icon || '',
image: options.image || '',
timeout: options.timeout || DEFAULT_SHOW_TOAST_TIME
};
if (type === 'global') {
globalToastUserConfig = {
...parsedDefaultOptions
};
} else if (type === 'page') {
let ctx = getPageCtx();
ctx.setData({
[`${TOAST_CONFIG_KEY}`]: parsedDefaultOptions
});
}
};
// 重置 toast 基础属性
Toast.resetDefaultOptions = function (type = 'page') {
if (type === 'global') {
globalToastUserConfig = {};
} else {
let ctx = getPageCtx();
ctx.setData({
[`${TOAST_CONFIG_KEY}`]: {}
});
}
};
// 清理所有 toast
Toast.clear = function () {
clearTimeout(timeoutData.timeoutId);
try {
timeoutData.toastCtx && timeoutData.toastCtx.clear();
} catch (e) {
console.log(e);
}
timeoutData = {
timeoutId: 0,
toastCtx: null
};
};
// 显示 loading
Toast.loading = function (options = {}) {
Toast({
...options,
type: 'loading'
});
};
module.exports = Toast;