1. 自定一个组件 TopBar
<template>
<!-- 顶部工具栏组件 -->
<div v-if="showNav" class="top-bar" :style="{ height: `${height}`, backgroundColor: `${backgroundColor}` }">
<!-- 顶部返回图标 默认显示 -->
<div v-if="showBack" class="icon icon-back" @click="handleBack"/>
<!-- 顶部标题 -->
<span class="title">{{ title }}</span>
<!-- 顶部更多图标 默认不显示 -->
<div v-if="showMore" class="icon icon-more" @click="handleMore"/>
<!-- 顶部分享图标 默认不显示 -->
<div v-if="showShare" class="icon icon-share" :class="[{ 'icon-share-adjusted': !showMore }]" @click="handleShare"/>
</div>
</template>
<script setup lang="ts">
import { callNativeFunction, closeWebView } from '@/utils/clientBridge';
import { computed, defineProps, onMounted, ref, withDefaults } from 'vue';
interface Props {
showNav?: boolean;
title?: string;
backgroundColor?: string;
height?: string;
showBack?: boolean;
showShare?: boolean;
showMore?: boolean;
}
// 使用 withDefaults 为 props 设置默认值
const props = withDefaults(defineProps<Props>(), {
showNav: true,
title: '',
backgroundColor: '#000',
height: '44px',
showBack: true,
showShare: false,
showMore: false,
});
const emit = defineEmits<{
(event: 'bar-icon-click',type:string): void;
}>();
function handleBack() {
// 调用客户端返回协议
closeWebView();
}
// TODO: 调用客户端更多协议
function handleMore() {
window.console.log('调用客户端更多协议');
emit("bar-icon-click","more")
}
// TODO: 调用客户端分享协议
function handleShare() {
window.console.log('调用客户端分享协议');
emit("bar-icon-click","share")
}
</script>
<style lang="less" scoped>
@import '~@/assets/styles/common.less';
.top-bar {
width: 100vw;
position: relative;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.icon {
width: 24px;
height: 24px;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
.icon-back {
background-image: url('../../assets/images/df_icon_back.png');
position: absolute;
left: 16px;
}
.icon-more {
background-image: url('../../assets/images/df_icon_more.png');
position: absolute;
right: 16px;
}
.icon-more-adjusted {
right: 56px;
}
.icon-share {
background-image: url('../../assets/images/df_icon_share.png');
position: absolute;
right: 56px;
}
.icon-share-adjusted {
right: 16px;
}
.title {
font-family: Poppins;
text-align: center;
color: #fff;
font-size: 18px;
font-weight: 500;
line-height: normal;
text-transform: capitalize;
letter-spacing: 0px;
}
}
</style>
其中,定义了一个事件回调
const emit = defineEmits<{
(event: 'bar-icon-click',type:string): void;
}>();
触发回调的逻辑:
// TODO: 调用客户端更多协议
function handleMore() {
window.console.log('调用客户端更多协议');
emit("bar-icon-click","more")
}
// TODO: 调用客户端分享协议
function handleShare() {
window.console.log('调用客户端分享协议');
emit("bar-icon-click","share")
}
2. 父视图中调用子组件,对事件的实现
<template>
<div class="video-preview no-select" @click.capture="handleCaptureClick">
<TopBar title="" :showShare="true" :showNav="true" :show-more="true" backgroundColor="#03141A"
@bar-icon-click="barClickHandle" id="top-bar-id"/>
</div>
</template>
<script lang="ts" setup>
import TopBar from '@/components/TopBar/index.vue';
const {proxy} = getCurrentInstance()!;
const barClickHandle = (type) => {
console.log("barClickHandle", type)
if ("more" === type) {
showMenuPop.value = true
}
if ("share" === type && selectedTemplate.value) {
if (selectedTemplate.value.id) {
let title = "Try the great template!"
let templateId = selectedTemplate.value.id
openLoadingIcon()
getClientUserInfo().then(res => {
closeLoadingIcon()
if (res && res.userId) {
let shareUrl = "https://dreamfaceapp.com/share/template?userId=" + res.userId + "&channel=system&tempId=" + templateId
+ "&apn=com.dreamapp.dubhe"
if (getEnvStatus().isRelease) {
apiPostRequest(config.api.shortUrlGet, {url: shareUrl}).then(res => {
callShare(res.url || shareUrl, title)
}).catch(e => {
callShare(res.url || shareUrl, title)
})
} else {
callShare(shareUrl, title)
}
}
}).catch(e => {
closeLoadingIcon()
})
}
}
}
function callShare(url: string, title: string) {
let shareParams = {
title: title,
description: url,
remoteUrl: "",
localPath: "",
mimeType: "TEXT",
channel: "system"
}
callNativeShare(shareParams)
}
</script>
类似于 iOS 中 Delegate / Block 。