如何在 Nuxt.js 中配合 Element UI 使用微信开放标签
发布于 3 年前 作者 dye 4893 次浏览 来自 分享

微信把服务号的模板消息改成了订阅通知,而订阅通知是用开放标签 wx-open-subscribe 来订阅,而不管是在官方文档,还是在社区的帖子中,都只有普通 Vue 项目的用法,所以今天专门记录一下如何在 Nuxt.js 项目中,跟原有的 Element UI 一起搭配使用微信开放标签。
跟着官方文档的使用步骤走,因为开放标签使用步骤与微信 JS-SDK 类似,所以很多工作都不需要做,像 JS接口安全域名 之前已经配置过。然后引入 JS 文件,之前我用的是 1.4.0 版本的,现在换成 1.6.0 版本,这个 JS 文件我是在 nuxt.config.js 文件中引入的。

module.exports = {
	head: {
		script: [
			{src: 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'}
		]
	}
}

然后下一步,通过 config 接口注入权限验证配置并申请所需开放标签。这个因为之前要用 jsApi,所以也做过,只需要在里面加上需要的开放标签即可。我这里需要跳转小程序和服务号订阅通知 2 个开放标签。

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [
  	'updateAppMessageShareData',
  	'updateTimelineShareData'
  ], // 必填,需要使用的JS接口列表
  openTagList: [
  	'wx-open-launch-weapp',
  	'wx-open-subscribe'
  ] // 可选,需要使用的开放标签列表
});

这个时候如果你去页面中使用开放标签,控制台会报这个错误:Unknown custom element: <wx-open-subscribe> - did you register the component correctly?。因为开放标签属于自定义标签,Vue 和 Nuxt.js 会给予未知标签的警告。在普通的 Vue 项目中,可以在 main.js 中配置 Vue.config.ignoredElements = ['wx-open-launch-weapp', 'wx-open-subscribe']。而在 Nuxt.js 项目中,需要在 nuxt.config.js 中配置。(查看 nuxtjs 官方文档

module.exports = {
	vue: {
		config: {
			ignoredElements: ['wx-open-launch-weapp','wx-open-subscribe']
	    }
	}
}

现在就可以在页面中去使用开放标签了。先提醒一句,因为订阅通知只有已认证的服务号才可以使用,所以代码写好之后,需要部署到生产环境,在手机真机上进行验证调试,在测试环境以及开发者工具都是没办法验证的。一般我们在开发时,会使用 vconsole 进行调试,而在生产环境下,没有 vconsole,最好的工具就是 Chrome 浏览器的 inspect 功能,可以用来调试 Android 手机中的 H5 页面,不知道的可以了解一下。在官方文档的使用说明中有提到,对于Vue 等视图框架,为了避免 template 标签冲突的问题,可使用 <script type="text/wxtag-template"></script> 代替 <template></template>,来包裹插槽模版和样式。所以如果你的开放标签不显示,请先检查是不是这个有问题。在 vue 页面的 <template></template> 中添加 wx-open-subscribe

<template>
	<wx-open-subscribe template="QhsDLahvIjb8RAB8iC23-hTbsMtnhIgKNrcgXERTxk0" id="subscribe-btn">
	  <script type="text/wxtag-template">
	    <style>.btn { margin:10px; padding: 5px }</style>
	    <button class="btn">订阅通知</button>
	  </script>
	</wx-open-subscribe>	
</template>

这里 wx-open-subscribe 的 template 属性是模板的 id,订阅通知的模板需要先在公众号后台申请。将上述代码部署到生产环境之后,就可以在手机上看到按钮了,同时按钮点击后,也能弹出申请通知的弹框。


既然已经可以正常显示按钮和响应按钮点击事件了,接下来要考虑的就是怎么和现有的项目融合。首先,我觉得不应该专门写个按钮让用户订阅通知,而是应该当用户点击之前已有的按钮时,可以先弹出这个申请通知的弹框,然后用户允许或取消后,再走下面的流程。举个例子,我之前有个购买按钮,用户购买之后我想给用户发条购买成功的通知,那么我就应该把订阅通知的功能加到我这个购买按钮上,而不是再加个按钮让用户专门订阅这条通知。同时,我可能会在任何一个组件上(不仅仅是 Button,可能是一张图片),当用户点击的时候,申请发送某个通知, 所以这个订阅通知标签应该是和其他组件分离的,可以搭配任何组件使用,只是当用户点击其他组件的时候,我要触发这个订阅功能,弹出这个弹窗。所以样式这块就比较头疼,我项目中用的 UI 框架是 Element UI,我不希望在加这个订阅通知的时候,还要对我的 Element UI 做改动,那太不合理了,所以最好的处理方法就是把开放标签和需要添加订阅功能的那个组件作为兄弟节点,放在同一个父元素 div 里,然后利用子绝父相,把开放标签的 position 写为 absolute,然后父元素的 position 写为 relative,让开放标签覆盖需要添加订阅功能的那个组件,这样看着像是点击的那个组件,其实点击的是开放标签,就可以正常申请通知了,然后把那个组件的点击事件交给开放标签处理就可以了。总结下来,就是原先的按钮实现样式,开放标签实现申请通知,并处理点击事件。

<div style=""="position: relative;">
  <el-button size="medium" type="primary" round style="width:100%;height:100%;">去购买</el-button>
  <div class="" style="position:absolute;width:100%;height:100%;top:0px;">
    <wx-open-subscribe template="LRN2-ntyTNKhUCtbOlhTfhvLFEXVZHp1zeeftcbc2Q4" id="subscribe-btn" 
    style="position:absolute;width:100%;height:100%;left:0px;top:0px;overflow:hidden;" 
    @success="openSubscribeSuccess" @error="openSubscribeError">
      <script type="text/wxtag-template">
        <style>.btn { width: 100%; height: 500px;}</style>
        <div class="btn"></div>
      </script>
    </wx-open-subscribe>
  </div>
</div>

可以看到,在开放标签里面的样式中,我把 height 写成了 500px,因为插槽中模版的样式是和页面隔离的,所以写成 100% 是不行的,必须得有固定的高度,在社区中,名为猛的这位伙伴是获取的实际高度,我发现没必要,只要我在 wx-open-subscribe 里面,设置了 overflow,让内部超出的部分隐藏,就可以正常使用。要注意的是,这里的高度必须大于等于需要添加订阅功能的组件高度,这里我假设的是需要添加订阅功能的组件高度不超过 500px,否则就不够了,还得改大一点。然后 wx-open-subscribe 有 success 和 error 两个事件,我们像 click 点击事件一样,调用方法就可以了。


到了这里,开放标签 wx-open-subscribe 的使用差不多就成功了。但是如果以后很多地方都需要订阅不同的通知,难道每次都要把这一段代码复制一遍吗,这就不太合适了,所以最好的方案是把每个开放标签都封装成一个 Vue 组件,然后在每个用到的地方直接引入组件使用就可以了,非常 nice。下面是我 open-subscribe.vue 的内容。

<template>
  <div class="wx-open-subscribe-container" style="position:absolute;width:100%;height:100%;top:0px;">
    <wx-open-subscribe :template="templateId" id="subscribe-btn" style="position:absolute;width:100%;height:100%;left:0px;top:0px;overflow:hidden;" @success="openSubscribeSuccess" @error="openSubscribeError">
      <script type="text/wxtag-template">
        <style>.btn { width: 100%; height: 500px;}</style>
        <div class="btn"></div>
      </script>
    </wx-open-subscribe>
  </div>
</template>
<script>
export default {
  props: {
    templateId: {
      type: String,
      default() {
        return ''
      }
    }
  },
  methods: {
    openSubscribeSuccess(e) {
      this.$emit('open-subscribe-success', e.detail)
    },
    openSubscribeError(e) {
      this.$emit('open-subscribe-error', e.detail)
    }
  }
}
</script>

wx-open-subscribe 有一个属性 template,所以将其作为 prop,从父组件传值过来。wx-open-subscribe 有 2 个事件 success 和 error,所以使用 $emit,将值传给父组件,让父组件处理事件。下面是这个子组件在父组件中的使用。

<template>
	<div class="" style="position:relative;">
	  <el-button type="success" plain icon="el-icon-share" circle />
	  <open-subscribe
	    template-id="9KjxFrQpgHpDpvkw3Krk6N8URgPNn7j6inHUeNF0sQg"
	    @open-subscribe-success="openSubscribeSuccess"
	    @open-subscribe-error="openSubscribeError"
	  />
	</div>
</template>
<script>
import openSubscribe from '@/components/open-tags/open-subscribe.vue'
export default {
	components: {
	    openSubscribe
	},
	methods: {
		openSubscribeSuccess(e) {

		},
		openSubscribeError(e) {

		}
	}
}
</script>

可以看到,父组件在使用订阅通知子组件时,把模板 id 传进去,然后监听 open-subscribe-successopen-subscribe-error 两个事件,自己实现两个时间的处理即可。
至于其他的开放标签,原理差不多,下面为跳转小程序的开放标签封装的子组件 open-launch-weapp.vue。

<template>
  <div class="wx-open-launch-weapp-container" style="position:absolute;width:100%;height:100%;top:0px;">
    <wx-open-launch-weapp :username="username" :path="path" id="launch-btn" style="position:absolute;width:100%;height:100%;left:0px;top:0px;overflow:hidden;" @launch="openWeappLaunch" @error="openWeappError">
      <script type="text/wxtag-template">
        <style>.btn { width: 100%; height: 500px;}</style>
        <div class="btn"></div>
      </script>
    </wx-open-launch-weapp>
  </div>
</template>
<script>
export default {
  props: {
    username: {
      type: String,
      default() {
        return ''
      }
    },
    path: {
      type: String,
      default() {
        return ''
      }
    }
  },
  methods: {
    openWeappLaunch(e) {
      this.$emit('open-weapp-launch')
    },
    openWeappError(e) {
      this.$emit('open-weapp-error')
    }
  }
}
</script>

到底为止,就实现了在 Nuxt.js 中配合原有的 Element UI 使用微信开放标签,对之前的东西没有什么大的破坏,还算比较合理的,希望可以帮到你。

回到顶部