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: [
|
items: [
|
||||||
{
|
{
|
||||||
path: 'action-sheet',
|
path: 'action-sheet',
|
||||||
title: 'ActionSheet 上拉菜单',
|
title: 'ActionSheet 动作面板',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dialog',
|
path: 'dialog',
|
||||||
@ -203,6 +203,10 @@ module.exports = {
|
|||||||
path: 'pull-refresh',
|
path: 'pull-refresh',
|
||||||
title: 'PullRefresh 下拉刷新',
|
title: 'PullRefresh 下拉刷新',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'share-sheet',
|
||||||
|
title: 'ShareSheet 分享面板',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'swipe-cell',
|
path: 'swipe-cell',
|
||||||
title: 'SwipeCell 滑动单元格',
|
title: 'SwipeCell 滑动单元格',
|
||||||
@ -550,6 +554,10 @@ module.exports = {
|
|||||||
path: 'pull-refresh',
|
path: 'pull-refresh',
|
||||||
title: 'PullRefresh',
|
title: 'PullRefresh',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'share-sheet',
|
||||||
|
title: 'ShareSheet',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'swipe-cell',
|
path: 'swipe-cell',
|
||||||
title: 'SwipeCell',
|
title: 'SwipeCell',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user