mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat: add ShareSheet component
This commit is contained in:
parent
8144e3de50
commit
5080761cfe
46
src/share-sheet/README.md
Normal file
46
src/share-sheet/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# ShareSheet
|
||||
|
||||
### Install
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import { ShareSheet } from 'vant';
|
||||
|
||||
Vue.use(ShareSheet);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| options | Share options | *Option[]* | `[]` |
|
||||
| title | Title | *string* | - |
|
||||
| cancel-text | Cancel button text | *string* | `'Cancel'` |
|
||||
| description | Description | *string* | - |
|
||||
|
||||
### Data Structure of Option
|
||||
|
||||
| Key | Description | Type |
|
||||
|------|------|------|
|
||||
| name | Option name | *string* |
|
||||
| icon | Option icon,can be set to `wechat` `link` `qrcode` `poster` or image URL | *string* |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| select | Triggered when click option | *option: Option, index: number* |
|
||||
| cancel | Triggered when click cancel button | - |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| title | Custom title |
|
||||
| description | Custom description |
|
66
src/share-sheet/README.zh-CN.md
Normal file
66
src/share-sheet/README.zh-CN.md
Normal file
@ -0,0 +1,66 @@
|
||||
# ShareSheet 分享面板
|
||||
|
||||
### 介绍
|
||||
|
||||
底部弹起的模态面板,用于展示各分享渠道对应的操作按钮,不包含具体的分享逻辑。2.6 版本开始支持此组件。
|
||||
|
||||
### 引入
|
||||
|
||||
```js
|
||||
import Vue from 'vue';
|
||||
import { ShareSheet } from 'vant';
|
||||
|
||||
Vue.use(ShareSheet);
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础用法
|
||||
|
||||
```html
|
||||
<van-share-sheet :options="options" />
|
||||
```
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| options | 分享选项 | *Option[]* | `[]` |
|
||||
| title | 顶部标题 | *string* | - |
|
||||
| cancel-text | 取消按钮文字 | *string* | `'取消'` |
|
||||
| description | 标题下方的辅助描述文字 | *string* | - |
|
||||
|
||||
### Option 数据结构
|
||||
|
||||
`options`属性为一个对象数组,数组中的每个对象配置一列,对象可以包含以下值:
|
||||
|
||||
| 键名 | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| name | 分享渠道名称 | *string* |
|
||||
| icon | 图标,可选值为 `wechat` `link` `qrcode` `poster`,支持传入图片 URL | *string* |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| select | 点击分享选项时触发 | *option: Option, index: number* |
|
||||
| cancel | 点击取消按钮时触发 | - |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| title | 自定义顶部标题 |
|
||||
| description | 自定义描述文字 |
|
52
src/share-sheet/demo/index.vue
Normal file
52
src/share-sheet/demo/index.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-cell
|
||||
is-link
|
||||
:title="t('showSheet')"
|
||||
@click="showBasicSheet = true"
|
||||
/>
|
||||
<van-share-sheet v-model="showBasicSheet" :options="options" />
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
i18n: {
|
||||
'zh-CN': {
|
||||
link: '复制链接',
|
||||
wechat: '微信',
|
||||
poster: '分享海报',
|
||||
qrcode: '二维码',
|
||||
showSheet: '显示分享面板',
|
||||
},
|
||||
'en-US': {
|
||||
link: 'Link',
|
||||
wechat: 'Wechat',
|
||||
poster: 'Poster',
|
||||
qrcode: 'Qrcode',
|
||||
showSheet: 'Show ShareSheet',
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showBasicSheet: false,
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.options = [
|
||||
{ name: this.t('wechat'), icon: 'wechat' },
|
||||
{ name: this.t('link'), icon: 'link' },
|
||||
{ name: this.t('poster'), icon: 'poster' },
|
||||
{ name: this.t('qrcode'), icon: 'qrcode' },
|
||||
];
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../style/var';
|
||||
</style>
|
97
src/share-sheet/index.js
Normal file
97
src/share-sheet/index.js
Normal file
@ -0,0 +1,97 @@
|
||||
// Utils
|
||||
import { createNamespace, isDef } from '../utils';
|
||||
|
||||
// Mixins
|
||||
import { popupMixinProps } from '../mixins/popup';
|
||||
|
||||
// Components
|
||||
import Popup from '../popup';
|
||||
|
||||
const PRESET_ICONS = ['wechat', 'link', 'qrcode', 'poster'];
|
||||
|
||||
const [createComponent, bem, t] = createNamespace('share-sheet');
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
...popupMixinProps,
|
||||
title: String,
|
||||
cancelText: String,
|
||||
description: String,
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onCancel() {
|
||||
this.toggle(false);
|
||||
},
|
||||
|
||||
onSelect(option, index) {
|
||||
this.$emit('select', option, index);
|
||||
},
|
||||
|
||||
toggle(val) {
|
||||
this.$emit('input', val);
|
||||
},
|
||||
|
||||
getIconURL(icon) {
|
||||
if (PRESET_ICONS.indexOf(icon) !== -1) {
|
||||
return `https://img.yzcdn.cn/vant/share-icon-${icon}.svg`;
|
||||
}
|
||||
|
||||
return icon;
|
||||
},
|
||||
|
||||
genOptions() {
|
||||
return (
|
||||
<div class={bem('options')}>
|
||||
{this.options.map((option, index) => (
|
||||
<div
|
||||
class={bem('option')}
|
||||
onClick={() => {
|
||||
this.onSelect(option, index);
|
||||
}}
|
||||
>
|
||||
<img src={this.getIconURL(option.icon)} class={bem('icon')} />
|
||||
<span class={bem('name')}>{option.name || ''}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
genCancelText() {
|
||||
const cancelText = isDef(this.cancelText) ? this.cancelText : t('cancel');
|
||||
|
||||
if (cancelText) {
|
||||
return (
|
||||
<button type="button" class={bem('cancel')} onClick={this.onCancel}>
|
||||
{cancelText}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Popup
|
||||
round
|
||||
class={bem()}
|
||||
value={this.value}
|
||||
position="bottom"
|
||||
safeAreaInsetBottom={this.safeAreaInsetBottom}
|
||||
onInput={this.toggle}
|
||||
>
|
||||
{this.genOptions()}
|
||||
{this.genCancelText()}
|
||||
</Popup>
|
||||
);
|
||||
},
|
||||
});
|
69
src/share-sheet/index.less
Normal file
69
src/share-sheet/index.less
Normal file
@ -0,0 +1,69 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-share-sheet {
|
||||
&__options {
|
||||
display: flex;
|
||||
padding: 16px 0 16px 24px;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
// fix right-padding issue for overflow-x element
|
||||
// see: https://stackoverflow.com/questions/10054870
|
||||
&::after {
|
||||
display: block;
|
||||
width: 24px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
&__option {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 32px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: @active-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
&__name {
|
||||
margin-top: 8px;
|
||||
color: #646566;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&__cancel {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
background-color: @white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&::before {
|
||||
display: block;
|
||||
height: 8px;
|
||||
background-color: @background-color;
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: @active-color;
|
||||
}
|
||||
}
|
||||
}
|
13
src/share-sheet/test/__snapshots__/demo.spec.js.snap
Normal file
13
src/share-sheet/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,13 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div role="button" tabindex="0" class="van-cell van-cell--clickable">
|
||||
<div class="van-cell__title"><span>显示分享面板</span></div><i class="van-icon van-icon-arrow van-cell__right-icon">
|
||||
<!----></i>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
4
src/share-sheet/test/demo.spec.js
Normal file
4
src/share-sheet/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
||||
import Demo from '../demo';
|
||||
import { snapshotDemo } from '../../../test/demo';
|
||||
|
||||
snapshotDemo(Demo);
|
@ -177,7 +177,7 @@ module.exports = {
|
||||
items: [
|
||||
{
|
||||
path: 'action-sheet',
|
||||
title: 'ActionSheet 上拉菜单',
|
||||
title: 'ActionSheet 动作面板',
|
||||
},
|
||||
{
|
||||
path: 'dialog',
|
||||
@ -203,6 +203,10 @@ module.exports = {
|
||||
path: 'pull-refresh',
|
||||
title: 'PullRefresh 下拉刷新',
|
||||
},
|
||||
{
|
||||
path: 'share-sheet',
|
||||
title: 'ShareSheet 分享面板',
|
||||
},
|
||||
{
|
||||
path: 'swipe-cell',
|
||||
title: 'SwipeCell 滑动单元格',
|
||||
@ -550,6 +554,10 @@ module.exports = {
|
||||
path: 'pull-refresh',
|
||||
title: 'PullRefresh',
|
||||
},
|
||||
{
|
||||
path: 'share-sheet',
|
||||
title: 'ShareSheet',
|
||||
},
|
||||
{
|
||||
path: 'swipe-cell',
|
||||
title: 'SwipeCell',
|
||||
|
Loading…
x
Reference in New Issue
Block a user