总结uniapp中做开屏广告的操作流程
具体逻辑流程
使用uniapp做开屏广告的一些基础问题,可以参考我以前发布的一篇文章(如何设置等):
https://www.wubin.work/blog/articles/286
这里主要讲一下各个页面的操作流程。首先来看流程图:
所以这里我们在pages目录中准备3个基础页面,分别是:
- APP.vue:uniapp工程目录中的启动页面,在根目录下
- pages/index.vue:app的主页,加载过后首先进入的页面
- pages/pop.vue:专门用于展示开屏广告的页面
- pages/webview-pop:专门用于打开开屏广告链接,承载跳转链接的页面,要求当在此页面上时,无论点击默认的顶部返回按钮或者安卓上的虚拟按键返回,都不会返回pop.vue,都会指向主页index.vue
然后不要忘记,需要上pop、webview-pop、index都必须在pages.json中注册:
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
//取消原生导航栏
"navigationStyle": "custom",
"navigationBarTitleText": "信号新闻",
"app-plus": {
"titleNView": false
}
}
},
{
"path" : "pages/pop/pop",
"style" :
{
"navigationStyle": "custom",
"navigationBarTitleText": "开屏广告",
"enablePullDownRefresh": false,
"app-plus": {
"titleNView": false,
"animationType": "fade-in",
"animationDuration": 300
}
}
},
{
"path" : "pages/webview-pop/webview-pop",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
],
手动启动以及POP页面结构
首先是开屏广告的接口数据结构(参考):
{
loading: {
has: false,
type: "image",
title: "12中全会顺利闭幕",
bg_url: "http://192.168.1.102/xcx/pop-open-w480.jpg",
link_mode: "webview",
link: "http://m.qdxin.cn/detail/286146.html"
},
...
}
APP.VUE中,获取所有数据接口,并保存到vuex中
import { mapActions } from 'vuex';
methods: {
...mapActions([
'updateAd',
'updateSomeData1',
'updateSomeData2'
])
}
在onLaunch中:
Promise.all([
getAd(),
getYY(),
getzz()
])
.then(([
ad,
y,
z,
]) => {
// 将获取到的数据存入vuex中
this.updateAd(ad);
this.updateSomeData1(y);
this.updateSomeData1(z);
// 如果开屏广告存在
if(ad.loading.has) {
// 那么重定向到pop页,并关闭启动页
uni.reLaunch({
url: '/pages/pop/pop',
success() {
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen();
// #endif
}
});
} else {
// 如果开屏广告不存在,那么定向到index
uni.reLaunch({
url:'/pages/index/index',
success() {
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen();
// #endif
}
});
}
});
pop中获取广告数据,并展示等
<template>
<view>
<pop-loading :loadingSetting="statusAD"
@popOk="popOk"
></pop-loading>
</view>
</template>
<script>
import PopLoading from '@/components/pop-loading/pop-loading.vue';
import { mapGetters } from 'vuex';
export default {
data() {
return {};
},
onLoad() {},
computed: {
...mapGetters([
'statusAD'
])
},
methods: {
popOk() {
// 广告展示结束时,跳到首页
uni.reLaunch({
url:'/pages/index/index',
success() {}
});
}
},
components: {
PopLoading
}
}
</script>
<style lang="less"></style>
先上一个工具函数,主要作用就是打开webview-pop这个单独的page的,因为避免链接长度太长,使用事件的方式传递参数:
export function goWebviewPop(weburl, title = '') {
// 为避免url太长,使用events传递数据
const url = `/pages/webview-pop/webview-pop`;
return new Promise((resolve, reject) => {
uni.navigateTo({
url: url,
animationType: 'pop-in',
animationDuration: 200,
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
events:{},
success: function(res) {
res.eventChannel.emit('getData', {
weburl: weburl,
title: title
}) //触发事件
resolve(true);
},
fail: function() {
reject(false);
}
});
});
}
pop-loading.vue(简化版):
<template>
<view class="pop-wrapper">
<view class="close"
@click.stop="close"
v-show="showCounting"
>
跳过
<text class="count-down">{{ countDown }}</text>
</view>
<view class="image-box"
@click="openLink"
>
<image :src="loadingSetting.bg_url"
mode="aspectFill"
@load="startPop"
></image>
</view>
</view>
</template>
<script>
import { goWebviewPop } from '@/common/js/until.js';
const TYPE_WEBVIEW = 'webview';
export default {
name:"popLoading",
emits: ['popOk'],
props: {
loadingSetting: {
type: Object,
default() {
return {}
}
}
},
created() {},
data() {
return {
showPop: true,
countDown: 6,
showCounting: false,
timer: null
};
},
methods: {
async openLink() {
// 当链接不存在或者模式为nolink的时候 阻挡点击事件
if(!this.loadingSetting.link ||
this.loadingSetting.link_mode == 'nolink'
) {
return;
}
// 有链接则执行跳转
const res = await goWebviewPop(this.loadingSetting.link);
// 如果打开webv失败,直接跳转到首页
if(!res) {
uni.reLaunch({
url:`/pages/index/index`,
success() {}
});
}
},
countDowning() {
if(this.timer) {
return;
}
this.timer = setInterval(() => {
this.countDown--;
if(this.countDown == 0) {
this.close();
clearInterval(this.timer);
}
}, 1000);
},
close() {
this.showPop = false;
this.$emit('popOk');
},
// 当图片加载完成后 执行倒计时
startPop() {
this.showCounting = true;
this.countDowning();
}
},
watch: {},
components: {
// 这里我实际上使用了UniTransition这个动画组件
// 可以参考使用https://uniapp.dcloud.net.cn/component/uniui/uni-transition.html#介绍
// UniTransition
}
}
</script>
<style lang="less"></style>
样式就不展示了,就是简单的fixed布局。这里我实际上使用了UniTransition这个动画组件,外包在外层,如下:
<template>
<uni-transition mode-class="fade"
:show="loadingSetting.has && showPop"
@change="change"
custom-class="pop-loading"
>
...
</uni-transition>
</template>
可以参考使用https://uniapp.dcloud.net.cn/component/uniui/uni-transition.html#介绍
核心:链接着陆页的处理
对原生顶部导航栏的默认返回进行修改(以及安卓上的虚拟按键返回)
实现这个流程的核心就是当点击链接的时候,跳转到着陆页webview-pop上,当我们不使用自定义顶部bar的时候,使用原生的bar,默认返回的是上一页pop.vue,所以我们需要修改它返回的目的地,这里我们就用到了uni的一个钩子函数:onBackPress。
参考链接:https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle
onBackPress | 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解 | app、H5、支付宝小程序 |
就是当点击手机上虚拟返回与UI中的返回的时候,都会触发这个钩子,在这里,我们将其指向我们的目的地,这里是指向index。
webview-pop.vue:
<template>
<view class="web-view">
<web-view :webview-styles="webviewStyles"
:src="webUrl"
fullscreen="true"
update-title="true"
></web-view>
</view>
</template>
<script>
export default {
name: 'webview',
data() {
return {
webUrl: '',
title: '',
webviewStyles: {
// 进度条
progress: {
color: '#FF3333'
}
}
}
},
// 点击返回按钮时执行的跳转
onBackPress(options) {
// if (options.from === 'navigateBack') {
// return false;
// }
/*
event = {from:backbutton、 navigateBack} ,backbutton
表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;
*/
uni.reLaunch({
url:'/pages/index/index',
success() {}
});
return true;
},
//option为object类型,会序列化上个页面传递的参数
async onLoad() {
// #ifdef APP-NVUE
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
// #endif
// #ifndef APP-NVUE
const eventChannel = this.getOpenerEventChannel();
// #endif
// 监听eventChannel传递过来的事件
eventChannel.on('getData', data => {
this.webUrl = data.weburl;
this.title = data.title;
// console.log(data);
});
},
watch: {
title(newval) {
if(newval) {
// console.log(newval);
uni.setNavigationBarTitle({
title: newval
});
}
}
}
}
</script>
<style></style>
至此我们实现了开屏广告的跳转不经过首屏,即可实现单独的webview页返回按钮能返回到首屏的整个流程。