投票H5的Vue实现
投票H5的Vue实现
最近一段时间明显感觉到业务在投票这一类的H5上聚集,每次都是业务部门提需求,设计出设计稿,然后到技术这边实现页面效果及投票逻辑。每次都在做这类机械的重复性工作,所以就想能不能进行一些抽象,用技术的手段将这些形成流水线(其实就是想把自己从中解放出来O(∩_∩)O哈哈~)。说干就干,跟后端的同学讨论了下,他也觉得有必要将这个独立开来,交到他们业务部门去。
在这里我只说前端H5用vue实现展示页面,因为后端管理系统这个很常规。
剥离页面配置属性
首先将一些可以公用的配置抽取出来,统一请求。这样在其他页面就可以不必浪费这个资源了。基本确定的要抽取出来的内容如下:
config: {
header: '', //头图
footer: '', //底部logo
share: '', //微信分享图片
bg_color: '', //背景色
title_color: '', //页面标题底色
button_color: '', //按钮颜色
progress_color: '' //进度条颜色
},
初步商定的公共资源也就这么多,准备是将这些配置统一请求用vuex状态管理。但是存在一个问题,当用户将子页面分享出去,其他人从分享页进入就造成拿不到配置。所以我将请求放在最外层的App.vue页面,如下:
<template>
<div :style="{backgroundColor: $store.state.config.bg_color}">
<router-view/>
</div>
</template>
<script>
import { ajax } from 'jquery'
export default {
name: 'App',
created() {
let that = this;
//路由配置
that.$store.dispatch('checkHost', process.env.NODE_ENV);
//请求配置数据
ajax({
type: 'get',
url: that.$store.state.Host+'/v/votes/'+that.$route.query.tt+'/config',
success: function(res) {
let config = {
header: res.header,
footer: res.footer,
share: res.share,
bg_color: res.bg_color,
title_color: res.title_color,
button_color: res.button_color,
progress_color: res.progress_color
};
that.$store.dispatch('catchConfig', config);
}
});
}
}
</script>
组件抽离
这里也没有多少能够通用的组件,一个是页面加载;另一个是分享引导。如图,
页面加载,
分享引导,
在这里遇到一个坑,加载的时候都还没什么问题。当在分享引导的时候在把引导页调出来后还有一个交互,一般是点击再隐藏。我把click事件放在组件上面,发现没有任何作用,然后在组件外包一层div,把click事件放在div上一切就ok了
//没有作用
<v-mock v-show="share" :style="{height: mock_height}" @click="shareCancel"></v-mock>
//改进后
<div @click="shareCancel">
<v-mock v-show="share" :style="{height: mock_height}"></v-mock>
<div class="clearfix"></div>
</div>
微信分享
关于微信分享,在微信公众号开发的官网也没有发现可以通过import引入的方式。每个页面都是独立的,也不能引入进去。不过还是感谢度娘,找到了一个说是微信官方出的weixin-js-sdk。对分享进行了一次封装,便于每个页面的不同分享配置。代码如下,
import {ajax} from 'jquery';
import wx from 'weixin-js-sdk';
var shareInfo = (function(mod) {
function identify(URL) {
var requestUrl = 'url';
ajax({
type:'post',
url:requestUrl,
data:{share_url:URL},
success:function(res) {
wx.config({
debug: false,
appId: res.data.appid,
timestamp: res.data.timestamp,
nonceStr: res.data.noncestr,
signature: res.data.signature,
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareQZone']
});
}
});
}
/**
* [init description]
* @author mao
* @version 1
* @date 2017-06-06
* @param {object} options 穿入参数
* img, title, desc, shareURL
*/
mod.init = function(options) {
//认证
identify(options.shareURL);
wx.ready(function(){
var imageurl = options.img,
title = options.title,
desc = options.desc,
link = options.shareURL;
wx.onMenuShareTimeline({
title: title,
desc: desc,
link: link,
imgUrl: imageurl,
success: function () {},
cancel: function () {}
});
wx.onMenuShareAppMessage({
title: title,
desc: desc,
link: link,
imgUrl: imageurl,
success: function () {},
cancel: function () {}
});
wx.onMenuShareQQ({
title: title,
desc: desc,
link: link,
imgUrl: imageurl,
success: function () {},
cancel: function () {}
});
wx.onMenuShareQZone({
title: title,
desc: desc,
link: link,
imgUrl: imageurl,
success: function () {},
cancel: function () {}
});
});
wx.error(function(res){
console.log(res);
});
}
return mod;
})(shareInfo || {});
export default shareInfo;
在这里我为什么用jQuery呢,其实还是有原因的。最初我也是用非常流行的axios,其他的地方请求都没有问题。但是就是在分享认证这里请求过来就报错,然后我又换了一个superagent发现返回报错一样。最后就换成了jQuery的ajax,这里可能后端同学对这个请求有限制吧。我知道是又一次是这样搞过的,不过因为后端同学也在忙没有跟他深究这个事情。留待后续讨论~
微信分享
其实这里还有一个比较大的bug,就是分享子页面出去如何从分享页进入到指定页面的问题。基本有以下两种思路,
- 使用动态路由,然后nginx配置相应的路由
- 使用带参数的动态路由
本着自己动手丰衣足食的优良品质,能不麻烦别人就不麻烦别人。明智的选择了第二种方式,但是在这里也存在一个隐患。在分享出去之后无论是在iOS端还是Android端微信都会给分享页面加上一些参数,比如,
iOS系统:'from=singlemessage&isappinstalled=0'
Android系统: 'from=singlemessage'
本来是一个单页应用,所以页面改变后会带着一些参数,最后再分享出去之后会把上述参数追加到后面。但是测试后发现用vue-router其实不必担心这个,因为通过key值找到固定的参数。后面query不会改变页面渲染。
前端存储
由于移动端有些网络状态不是很好,所以在交互上设计的策略是投票后就自动在前段把票数加上去,然后同时发post请求存储。这样就可以给用户有一个很好的交互。
{
奖项id: {
选项id: 票数,
选项id: 票数,
选项id: 票数,
上限: 票数
},
奖项id: {
选项id: 票数,
选项id: 票数,
选项id: 票数,
上限: 票数
}
}
在开发过程中老是不对,查了好久逻辑也没有任何问题。最后重头到尾有细细看了一下发现把变量名给搞错了。导致第一次进入的时候没问题,重复进入之后逻辑就不对了。所以敲代码还是要细心啊!
最后的效果如下图,