这篇文章次要是讲述自定义分享组件的方放,兼容网页 H5 端、微信小程序端和 App 端。

目录

  • 筹备工作
  • 原理剖析
  • 组件实现
  • H5 和 App
  • 小程序
  • 案例展现

筹备工作

  • 首先咱们从图标图库网站下面找一些罕用的分享图标并下载下来;
  • components新建一个q-share文件夹,并新建一个q-share.vue的组件;
  • 依照前一篇所说的页面构造,编写好预约的分享页面;

原理剖析

自定义分享组件就是采纳各端反对的 API 办法进行封装设置,利用条件编译的语法进行分而实现。

H5 端剖析

H5 端次要有两种分享办法:

  • 一般浏览器自带分享按钮;微信内嵌浏览器,可调用js-sdk进行分享;
  • 第三方平台网页利用:在第三方分享平台申请增加本人的利用,以便调用第三方的分享 API 进行分享;
  • 网上公共分享链接:这里就应用网上公开的分享地址进行分享了。

以下列举了几个罕用的第三方分享平台的地址,感兴趣的能够珍藏看一下。

罕用开放平台:

  • QQ 互联平台
  • 微信开放平台
  • 微博开放平台
  • 支付宝开放平台
  • 百度开放平台
  • 抖音开放平台

小程序端剖析

小程序端的分享目前 uniapp 不反对 API 调用,只能用户被动点击触发分享,可应用自定义按钮形式<button open-type="share">或监听系统右上角的分享按钮onShareAppMessage 进行自定义分享内容。

在这里能够查看微信小程序的分享 API进行小程序分享性能开发。

小程序文档:

  • 微信小程序
  • 支付宝小程序
  • 百度智能小程序

APP 端剖析

APP 端的分享能够自主管制分享的内容、模式及平台,提供了以下两种办法:

  • 应用uni.shareAPI 形式调用社交 sdk 分享;
  • 应用plus.share.sendWithSystem呼起手机零碎的分享菜单;

开发者官网:

  • 安卓开发者官网
  • 苹果开发者官网

快利用官网:

  • 华为快利用
  • 小米快利用
  • OPPO 快利用
  • vivo 快利用

组件实现

筹备工作和原理剖析实现后,接下来写一个简略的自定义分享组件。

模板局部

<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"> 零碎分享 </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);      }    }  }}

脚本局部

  • 引入依赖包和属性设置
import { ref, reactive, computed } from "vue";// 属性const showTimer = ref(null); // 显示提早const showTime = ref(100); // 显示延迟时间const showCloseTimer = ref(null); // 显示敞开提早const showCloseTime = ref(300); // 显示敞开延迟时间const shares = reactive({  show: false, // 显示分享框  showMask: false, // 显示模态框  showBox: false, // 显示内容动画  options: {    // 父组件音讯    dir: "down", // 内容方向    radius: 0, // 圆角角度    width: 200, // 内容宽度    height: 300, // 内容高度  },  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: "复制链接",      val: "link",      url() {        return location.href;      },    },    {      id: 19,      name: "更多",      val: "more",      url() {        return "";      },    },  ],  info: {    title: "", // 分享题目    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);}// 敞开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);  // 分享内容  let url = shares.info.url,    title = shares.info.title;  // 网页分享  // #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: "复制胜利!",          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: "列表页面",          summary: "我正在应用HelloApp,连忙跟我一起来体验!",          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",      });    }  }  // 敞开分享  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));    },  });}// #endifdefineExpose({  open,  close,});

H5 和 App

写好分享组件后,能够在 H5 和 App 外面应用了,上面是页面模板和脚本应用办法。

模板应用

<!-- 顶部导航组件引入 --><q-navbar :center="navConfig.center" :right="navConfig.right" @change="changeNav" /><!-- 分享组件引入 --><q-share ref="mineShare" @share="shareSetting" />

脚本应用

点击右上角分享图标,调用上面办法进行分享。

  • 定义数据
// 顶部导航配置const navConfig = reactive({  center: {    show: true,    name: "列表页面",  },  right: {    show: true,    icon: "more",    type: "self",  },});// 分享信息配置let shareInfo = reactive({  dir: "down",  radius: 20,  height: 350,  title: "列表页面",  url: "https://blog.example.com/#/pages/index/list?from=share",});
  • 办法调用
// 点击导航分享图标调用分享办法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: ƒ}}

小程序

在这里特地阐明一下小程序,因为 uniapp 不反对小程序的 API,因而这里依据小程序的文档封装了一个获取小程序参数的办法放在scriptsutils文件中。

获取参数

// 获取微信分享信息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(`获取微信小程序分享参数${params.type}:`, result);  return params;}

引入 API

接着就是页面引入 uniapp 的 API 和微信分享办法。

import { onLoad, onShareAppMessage, onShareTimeline, onAddToFavorites } from "@dcloudio/uni-app";

获取参数

onLoad((option) => {  // #ifdef MP-WEIXIN  // 设置微信分享  setWxShare();  // #endif});// #ifdef MP-WEIXIN// 设置微信分享function setWxShare(type = "message") {  const params = proxy.$apis.utils.getWxShare({    title: "列表页面",    query: "from=list",    type,  });  return params;}// #endif

监听转发事件

// #ifdef MP-WEIXIN// 转发到聊天界面onShareAppMessage((res) => {  const params = setWxShare("message");  return params;});// 转发到朋友圈onShareTimeline((res) => {  const params = setWxShare("friend");  return params;});// 增加到珍藏onAddToFavorites((res) => {  const params = setWxShare("favorite");  return params;});// #endif

案例展现

  • h5 端成果

  • 小程序端成果

  • APP 端成果

最初

以上就是自定义分享组件的次要内容,有不足之处,请多多斧正。