uniapp項(xiàng)目實(shí)踐自定義分享組件示例

準(zhǔn)備工作
這篇文章主要是講述自定義分享組件的方放,兼容網(wǎng)頁(yè) H5 端、微信小程序端和 App 端。
- 首先我們從圖標(biāo)圖庫(kù)網(wǎng)站上面找一些常用的分享圖標(biāo)并下載下來(lái);
- 在
components新建一個(gè)q-share文件夾,并新建一個(gè)q-share.vue的組件; - 按照前一篇所說(shuō)的頁(yè)面結(jié)構(gòu),編寫好預(yù)定的分享頁(yè)面;
原理分析
自定義分享組件就是采用各端支持的 API 方法進(jìn)行封裝設(shè)置,利用條件編譯的語(yǔ)法進(jìn)行分而實(shí)現(xiàn)。
H5 端分析
H5 端主要有兩種分享方法:
- 普通瀏覽器自帶分享按鈕;微信內(nèi)嵌瀏覽器,可調(diào)用js-sdk進(jìn)行分享;
- 第三方平臺(tái)網(wǎng)頁(yè)應(yīng)用:在第三方分享平臺(tái)申請(qǐng)?zhí)砑幼约旱膽?yīng)用,以便調(diào)用第三方的分享 API 進(jìn)行分享;
- 網(wǎng)上公共分享鏈接:這里就使用網(wǎng)上公開的分享地址進(jìn)行分享了。
以下羅列了幾個(gè)常用的第三方分享平臺(tái)的地址,感興趣的可以收藏看一下。
常用開放平臺(tái):
小程序端分析
小程序端的分享目前 uniapp 不支持 API 調(diào)用,只能用戶主動(dòng)點(diǎn)擊觸發(fā)分享,可使用自定義按鈕方式<button open-type="share">或監(jiān)聽系統(tǒng)右上角的分享按鈕onShareAppMessage 進(jìn)行自定義分享內(nèi)容。
在這里可以查看微信小程序的分享 API進(jìn)行小程序分享功能開發(fā)。
小程序文檔:
APP 端分析
APP 端的分享可以自主控制分享的內(nèi)容、形式及平臺(tái),提供了以下兩種方法:
- 使用uni.shareAPI 方式調(diào)用社交 sdk 分享;
- 使用plus.share.sendWithSystem呼起手機(jī)系統(tǒng)的分享菜單;
開發(fā)者官網(wǎng):
快應(yīng)用官網(wǎng):
組件實(shí)現(xiàn)
準(zhǔn)備工作和原理分析完成后,接下來(lái)寫一個(gè)簡(jiǎn)單的自定義分享組件。
模板部分
<view class="q-share" v-if="shares.show">
<view :class="{'q-share-mak': true, 'active': shares.showMask}" @click="close('mask')"></view>
<view
:class="{'q-share-inner': true, [shares.options.dir]: true, 'active': shares.showBox}"
:style="{'width': `${['left', 'right'].includes(shares.options.dir) ? shares.options.width + 'rpx' : '100%'}`, 'height': `${['up', 'down'].includes(shares.options.dir) ? shares.options.height + 'rpx' : '100%'}`, borderRadius: shares.options.radius+'rpx'}">
<slot name="box">
<view class="q-share-box">
<view class="q-share-title"> 系統(tǒng)分享 </view>
<scroll-view :scroll-x="true" class="q-share-content">
<view class="q-share-list" :style="{'width': shareList.length*145+'rpx'}">
<view
class="q-share-item"
v-for="item in shareList"
:key="item.id"
@click="shareSet(item)">
<q-icon class="q-share-item-icon" :name="item.val" :size="20" />
<text class="q-share-item-txt">{{item.name}}</text>
</view>
</view>
</scroll-view>
<view class="q-share-cancel" @click="close('cancel')"> 取消分享 </view>
</view>
</slot>
</view>
</view>樣式部分
.q-share {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100vh;
z-index: 199;
.q-share-mak {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.45);
transition: background 2s;
z-index: 90;
&.active {
background: rgba(0, 0, 0, 0.35);
}
}
.q-share-inner {
position: absolute;
max-width: 100%;
max-height: 100%;
background: rgba(255, 255, 255, 0.95);
transition: all 0.5s;
z-index: 95;
.q-share-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: 15rpx 25rpx;
width: 100%;
height: 100%;
.q-share-title {
width: 100%;
line-height: 3;
font-size: 28rpx;
color: $uni-text-color;
text-align: center;
}
.q-share-content {
flex: 1;
box-sizing: border-box;
padding: 20rpx;
width: 100%;
height: calc(100% - 140rpx);
.q-share-list {
display: flex;
flex-flow: row nowrap;
box-sizing: border-box;
padding: 25rpx 0;
height: 100%;
.q-share-item {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 145rpx;
height: 100%;
.q-share-item-icon {
padding: 0;
}
.q-share-item-txt {
margin-top: 10rpx;
font-size: 24rpx;
}
}
}
}
.q-share-cancel {
width: 100%;
line-height: 2;
font-size: 28rpx;
color: $uni-text-color-grey;
text-align: center;
}
}
&.down,
&.up {
left: 0;
}
&.down {
bottom: 0;
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
transform: translateY(100%);
&.active {
transform: translateY(0);
}
}
&.up {
top: 0;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
transform: translateY(-100%);
&.active {
transform: translateY(0);
}
}
&.left,
&.right {
top: 0;
width: 0;
}
&.left {
left: 0;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
transform: translateX(-100%);
&.active {
transform: translateX(0);
}
}
&.right {
right: 0;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
transform: translateX(100%);
&.active {
transform: translateX(0);
}
}
}
}腳本部分
- 引入依賴包和屬性設(shè)置
import { ref, reactive, computed } from "vue";
// 屬性
const showTimer = ref(null); // 顯示延遲
const showTime = ref(100); // 顯示延遲時(shí)間
const showCloseTimer = ref(null); // 顯示關(guān)閉延遲
const showCloseTime = ref(300); // 顯示關(guān)閉延遲時(shí)間
const shares = reactive({
show: false, // 顯示分享框
showMask: false, // 顯示模態(tài)框
showBox: false, // 顯示內(nèi)容動(dòng)畫
options: {
// 父組件消息
dir: "down", // 內(nèi)容方向
radius: 0, // 圓角角度
width: 200, // 內(nèi)容寬度
height: 300, // 內(nèi)容高度
},
list: [
{
id: 1,
name: "QQ",
val: "qq",
url(url, title) {
return `https://connect.qq.com/widget/shareqq/iframe_index.html?url=${url}&title=${title}`;
},
},
{
id: 2,
name: "QQ空間",
val: "qzone",
url(url, title) {
return `http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=${url}&title=${title}&site=${url}`;
},
},
{
id: 3,
name: "微博",
val: "weibo",
url(url, title) {
return `http://service.weibo.com/share/share.php?url=${url}&title=${title}&language=zh_cn`;
},
},
{
id: 4,
name: "微信",
val: "wechat",
url() {
return "";
},
},
{
id: 5,
name: "百度",
val: "baidu",
url() {
return "";
},
},
{
id: 6,
name: "貼吧",
val: "tieba",
url() {
return "";
},
},
{
id: 7,
name: "朋友圈",
val: "friend",
url() {
return "";
},
},
{
id: 8,
name: "淘寶",
val: "taobao",
url() {
return "";
},
},
{
id: 9,
name: "支付寶",
val: "alipay",
url() {
return "";
},
},
{
id: 10,
name: "釘釘",
val: "dingtalk",
url() {
return "";
},
},
{
id: 11,
name: "快手",
val: "gifks",
url() {
return "";
},
},
{
id: 12,
name: "Whatsapp",
val: "whatsapp",
url() {
return "";
},
},
{
id: 13,
name: "Messenger",
val: "messenger",
url() {
return "";
},
},
{
id: 14,
name: "Youtube",
val: "youtube",
url() {
return "";
},
},
{
id: 15,
name: "Instagram",
val: "instagram",
url() {
return "";
},
},
{
id: 16,
name: "Twitter",
val: "twitter",
url() {
return "";
},
},
{
id: 17,
name: "Telegram",
val: "telegram",
url() {
return "";
},
},
{
id: 18,
name: "復(fù)制鏈接",
val: "link",
url() {
return location.href;
},
},
{
id: 19,
name: "更多",
val: "more",
url() {
return "";
},
},
],
info: {
title: "", // 分享標(biāo)題
url: "", // 分享地址
},
});
const emits = defineEmits(["close", "share"]);- 分享方法定義
// 方法
// 分享列表
const shareList = computed(() => {
let newList = [],
mnp = ["qq", "qzone", "wechat", "friend"];
// #ifdef H5
newList = shares.list.filter((s) => s.val != "more");
// #endif
// #ifdef MP-WEIXIN
newList = shares.list.filter((s) => mnp.includes(s.val));
// #endif
// #ifdef APP-PLUS
newList = shares.list;
// #endif
return newList;
});
// 打開
function open(options) {
let defaultOptions = {
dir: "down",
radius: 0,
width: 500,
height: 300,
title: "",
url: "",
};
let params = { ...defaultOptions, ...options };
shares.show = true;
shares.options = { ...params };
shares.info = {
title: params.title,
url: params.url,
};
showTimer.value = setTimeout(() => {
shares.showMask = true;
shares.showBox = true;
clearTimeout(showTimer.value);
}, showTime.value);
}
// 關(guān)閉
function close(from = "") {
shares.showBox = false;
emits("close", from);
showTimer.value = setTimeout(() => {
shares.showMask = false;
clearTimeout(showTime.value);
}, showTime.value);
showCloseTimer.value = setTimeout(() => {
shares.show = false;
clearTimeout(showCloseTimer.value);
}, showCloseTime.value);
}
// 分享出去
function shareSet(info) {
// 通知父組件
emits("share", info);
// 分享內(nèi)容
let url = shares.info.url,
title = shares.info.title;
// 網(wǎng)頁(yè)分享
// #ifdef H5
url = url || location.href;
title = title || document.title;
// #endif
// 分享提示
if (info.val == "more") {
// #ifdef APP-PLUS
uni.shareWithSystem({
type: "text",
summary: title,
href: url,
success() {
uni.showToast({
title: "分享成功!",
icon: "success",
});
},
fail() {
uni.showToast({
title: "分享失敗!",
icon: "error",
});
},
});
// #endif
} else if (info.val == "link") {
uni.setClipboardData({
data: url,
success() {
uni.showToast({
title: "復(fù)制成功!",
icon: "success",
});
},
});
} else {
let shareUrl = info.url(url, title);
if (shareUrl) {
// #ifdef H5
window.open(shareUrl);
// #endif
// #ifdef APP-PLUS
if (plus) {
plus.runtime.openURL(shareUrl, (res) => {
console.log("shareUrl res:", res);
});
}
// #endif
} else {
// #ifdef APP-PLUS
const scene = "WXSceneSession",
params = {
href: "https://blog.example.com",
title: "列表頁(yè)面",
summary: "我正在使用HelloApp,趕緊跟我一起來(lái)體驗(yàn)!",
imageUrl: "https://blog.example.com/img/03.png",
};
// 分享到聊天界面
if (info.val == "wechat") {
appShareWx(scene, params);
}
// 分享到朋友圈
if (info.val == "friend") {
scene = "WXSceneTimeline";
appShareWx(scene, params);
}
// #endif
uni.showToast({
title: "分享成功!",
icon: "success",
});
}
}
// 關(guān)閉分享
close();
}
// #ifdef APP-PLUS
// 分享到聊天界面或朋友圈
function appShareWx(scene = "WXSceneSession", info) {
let { href, title, summary, imageUrl } = info;
uni.share({
provider: "weixin",
scene,
type: 0,
href,
title,
summary,
imageUrl,
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
},
});
}
// #endif
defineExpose({
open,
close,
});H5 和 App
寫好分享組件后,可以在 H5 和 App 里面使用了,下面是頁(yè)面模板和腳本使用方法。
模板使用
<!-- 頂部導(dǎo)航組件引入 --> <q-navbar :center="navConfig.center" :right="navConfig.right" @change="changeNav" /> <!-- 分享組件引入 --> <q-share ref="mineShare" @share="shareSetting" />
腳本使用
點(diǎn)擊右上角分享圖標(biāo),調(diào)用下面方法進(jìn)行分享。
- 定義數(shù)據(jù)
// 頂部導(dǎo)航配置
const navConfig = reactive({
center: {
show: true,
name: "列表頁(yè)面",
},
right: {
show: true,
icon: "more",
type: "self",
},
});
// 分享信息配置
let shareInfo = reactive({
dir: "down",
radius: 20,
height: 350,
title: "列表頁(yè)面",
url: "https://blog.example.com/#/pages/index/list?from=share",
});- 方法調(diào)用
// 點(diǎn)擊導(dǎo)航分享圖標(biāo)調(diào)用分享方法
function changeNav(info) {
if (info.from == "right" && info.icon == "more") {
if (proxy.$refs.mineShare) {
proxy.$refs.mineShare.open(shareInfo);
}
}
}
// 分享組件返回分享信息
function shareSetting(info) {
console.log("分享消息:", info); // 分享消息: Proxy(Object) {id: 4, name: '微信', val: 'wechat', url: ?}
}小程序
在這里特別說(shuō)明一下小程序,由于 uniapp 不支持小程序的 API,因此這里根據(jù)小程序的文檔封裝了一個(gè)獲取小程序參數(shù)的方法放在scripts的utils文件中。
獲取參數(shù)
// 獲取微信分享信息
function getWxShare(options) {
let pages = getCurrentPages(),
page = pages[pages.length - 1],
defaultOptions = {
title: "HelloApp",
path: `/${page.route}`,
imageUrl: "",
query: "from=list",
promise: null,
type: "message", // message 聊天界面,friend 朋友圈,favorite 收藏
res: {},
};
let params = {
...defaultOptions,
...options,
};
const { title, imageUrl, path, query, promise } = params;
const message = {
path: `${path}?${query}`,
imageUrl,
title,
promise,
};
const friend = {
path,
query,
imageUrl,
title,
};
const favorite = {
title,
imageUrl,
query,
};
const shares = {
message,
friend,
favorite,
};
const result = shares[params.type];
console.log(`獲取微信小程序分享參數(shù)${params.type}:`, result);
return params;
}引入 API
接著就是頁(yè)面引入 uniapp 的 API 和微信分享方法。
import { onLoad, onShareAppMessage, onShareTimeline, onAddToFavorites } from "@dcloudio/uni-app";獲取參數(shù)
onLoad((option) => {
// #ifdef MP-WEIXIN
// 設(shè)置微信分享
setWxShare();
// #endif
});
// #ifdef MP-WEIXIN
// 設(shè)置微信分享
function setWxShare(type = "message") {
const params = proxy.$apis.utils.getWxShare({
title: "列表頁(yè)面",
query: "from=list",
type,
});
return params;
}
// #endif監(jiān)聽轉(zhuǎn)發(fā)事件
// #ifdef MP-WEIXIN
// 轉(zhuǎn)發(fā)到聊天界面
onShareAppMessage((res) => {
const params = setWxShare("message");
return params;
});
// 轉(zhuǎn)發(fā)到朋友圈
onShareTimeline((res) => {
const params = setWxShare("friend");
return params;
});
// 添加到收藏
onAddToFavorites((res) => {
const params = setWxShare("favorite");
return params;
});
// #endif案例展示
- h5 端效果

- 小程序端效果

- APP 端效果

最后
以上就是自定義分享組件的主要內(nèi)容,更多關(guān)于uniapp自定義分享組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于JavaScript數(shù)組對(duì)象去重的幾種方法
這篇文章主要介紹了關(guān)于JavaScript數(shù)組對(duì)象去重的幾種方法,不管是map對(duì)象的特性還是reduce方法都是很好用的去重方法,需要的朋友可以參考下2023-04-04
js輸入框使用正則表達(dá)式校驗(yàn)輸入內(nèi)容的實(shí)例
下面小編就為大家?guī)?lái)一篇js輸入框使用正則表達(dá)式校驗(yàn)輸入內(nèi)容的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
typescript編寫微信小程序創(chuàng)建項(xiàng)目的方法
這篇文章主要介紹了typescript編寫微信小程序創(chuàng)建項(xiàng)目的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
JavaScript表單驗(yàn)證的兩種實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了JavaScript表單驗(yàn)證的兩種實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
JavaScript之IE的fireEvent方法詳細(xì)解析
剛開始我以為是會(huì)跟平時(shí)使用onclick()一樣,沒(méi)想到最近在寫javascript入門ppt的時(shí)候發(fā)現(xiàn)了,原來(lái)自己太自以為是了!看來(lái)還有很多javascript的細(xì)節(jié)沒(méi)有掌握好啊2013-11-11

