跨端開(kāi)發(fā)框架avm組件封裝經(jīng)驗(yàn)分享
引言
avm.js 是一個(gè)跨端開(kāi)發(fā)框架,AVM(Application-View-Model)前端組件化開(kāi)發(fā)模式基于標(biāo)準(zhǔn)Web Components組件化思想,提供包含虛擬DOM和Runtime的編程框架avm.js以及多端統(tǒng)一編譯工具,完全兼容Web Components標(biāo)準(zhǔn),同時(shí)兼容Vue和React語(yǔ)法糖編寫(xiě)代碼,編譯工具將Vue和React相關(guān)語(yǔ)法糖編譯轉(zhuǎn)換為avm.js代碼。
有Vue和React 開(kāi)發(fā)經(jīng)驗(yàn)的很容易上手。
1. 組件的定義和引用:
1.1 使用stml定義一個(gè)組件 / 頁(yè)面
stml組件兼容Vue單文件組件(SFC)規(guī)范,使用語(yǔ)義化的Html模板及對(duì)象化js風(fēng)格定義組件或頁(yè)面。stml最終被編譯為JS組件 / 頁(yè)面,渲染到不同終端。
定義組件:
// api-test.stml:
<template>
<view class='header'>
<text>{this.data.title}</text>
</view>
</template>
<script>
export default {
name: 'api-test',
data(){
return {
title: 'Hello APP'
}
}
}
</script>
<style scoped>
.header{
height: 45px;
}
</style>1.2 組件引用:
// app-index.stml:
<template>
<view class="app">
<img src="./assets/logo.png" />
<api-test></api-test>
</view>
</template>
<script>
import './components/api-test.stml'
export default {
name: 'app-index',
data: function () {
return {
title: 'Hello APP'
}
}
}
</script>
<style>
.app {
text-align: center;
margin-top: 60px;
}
</style>2. 向子組件傳值
向子組件傳值采用 props 的方式,這里以一個(gè)示例來(lái)進(jìn)行說(shuō)明。
定義子組件,在 props 里面注冊(cè)一個(gè) title 屬性:
// api-test.stml:
<template>
<text>{title}</text>
</template>
<script>
export default {
name:'api-test',
props:{
title: String
}
}
</script>這里定義的title屬性類型為String,屬性類型包括 String、Number、Boolean、Array、Object、Function等。
2.1 在其它頁(yè)面使用子組件時(shí)傳遞靜態(tài)值:
// app-index.stml:
<template>
<view>
<api-test title="Hello App!"></api-test>
</view>
</template>
<script>
import './components/api-test.stml'
export default {
name: 'app-index'
}
</script>2.2 通過(guò)數(shù)據(jù)綁定傳遞動(dòng)態(tài)值:
// app-index.stml:
<template>
<view>
<api-test v-bind:title="msg"></api-test>
</view>
</template>
<script>
import './components/api-test.stml'
export default {
name: 'app-index',
data() {
return {
msg: 'Hello App!'
}
}
}
</script>傳遞靜態(tài)值時(shí)只能傳遞字符串類型數(shù)據(jù),通過(guò)數(shù)據(jù)綁定的方式則可以傳遞任意類型的數(shù)據(jù)。
3. 監(jiān)聽(tīng)子組件事件**
監(jiān)聽(tīng)子組件事件和監(jiān)聽(tīng)普通事件類似,如:
// api-index.stml:
<template>
<view>
<api-test onresult="onGetResult"></api-test>
</view>
</template>
<script>
import './components/api-test.stml'
export default {
name: 'app-index',
methods: {
onGetResult(e){
console.log(e.detail.msg);
}
}
}
</script>以上示例中監(jiān)聽(tīng)了子組件的result事件,子組件里面通過(guò)fire方法來(lái)觸發(fā)監(jiān)聽(tīng)的事件:
// app-test.stml:
<template>
<text onclick="onclick">Hello App!</text>
</template>
<script>
export default {
name:'api-test',
methods:{
onclick(){
let detail = {msg:'Hi'};
this.fire('result', detail);
}
}
}
</script>fire方法有兩個(gè)參數(shù),第一個(gè)參數(shù)為事件名稱,第二個(gè)參數(shù)為要傳遞的自定義數(shù)據(jù),在父組件監(jiān)聽(tīng)方法里面通過(guò)e.detail獲取傳遞的數(shù)據(jù)。
// api-index.stml:
methods: {
onGetResult(e){
console.log(e.detail.msg);
}
}4. 聲網(wǎng)組件實(shí)例
了解了以上組件的規(guī)則和用法,就可以封裝自己的組件了 。下面看一個(gè)基于agoraRtc聲網(wǎng)模塊,實(shí)現(xiàn)1對(duì)1語(yǔ)音通話的組件實(shí)例:
<template>
<view class="agorartc-call-voice_page">
<safe-area></safe-area>
<view class="agorartc-call-voice_list" v-for="(item,index) in userList">
<view class="agorartc-call-voice_userinfo">
<image class="agorartc-call-voice_userinfo-image" thumbnail='false'
style="width: 64px; height: 64px; margin-right:10px" src={{item.userimg }}></image>
<text class="agorartc-call-voice_userinfo-text">{{item.username }}</text>
</view>
<view class="agorartc-call-voice_callimg">
<image @click="fnstart_voice_call(item.userid)" thumbnail='false' style="width: 50px; height: 50px"
src="../../image/voice-call.png"></image>
</view>
</view>
<view class="agorartc-call-voice_connected" v-if="connected">
<image class="agorartc-call-voice_voice" thumbnail='false' style="width: 200px;"
src="../../image/video-voice.gif"></image>
<image class="agorartc-call-voice_hangup" @click="fnhangup()" thumbnail='false'
style="width: 64px; height: 64px;" src="../../image/video-hangup.png"></image>
</view>
</view>
</template>
<script>
export default {
name: 'agorartc-call-voice',
props: {
channel: String,
userList: Array,
rtcAppId: String
},
installed() {
this.fnishasper_mic();
},
data() {
return {
connected: false
};
},
methods: {
fnishasper_mic(_userid) {
var resultList = api.hasPermission({
list: ["microphone"]
});
if (resultList[0].granted) {
} else {
api.toast({
msg: "需要啟用麥克風(fēng)權(quán)限"
});
api.requestPermission({
list: ["microphone"]
}, res => {
if (res.list[0].granted) {
}
});
}
},
fnstart_voice_call(_userid) {
this.fnrtc_init();
this.fnerr_listener();
this.fnjoin_channel(_userid);
},
fnrtc_init() {
console.log('初始化');
var agoraRtc = api.require('agoraRtc');
agoraRtc.init({
appId: this.props.rtcAppId
});
},
fnjoin_channel(_userid) {
console.log('121:---' + _userid);
this.data.connected = true;
var agoraRtc = api.require('agoraRtc');
agoraRtc.joinChannelSuccessListener(function (ret) {
console.log(ret.uid + 'uid------');
});
agoraRtc.remoteUserJoinedListener((ret) => {
console.log(ret.uid + 'remoteUserJoinedListener------');
if (ret.uid) {
this.data.connected = true;
}
});
// 多人語(yǔ)音通話 ,需設(shè)置角色為主播
agoraRtc.setClientRole({
role: 1
}, function (ret) {
if (ret.code == 0) {
//success
console.log('設(shè)置主播模式成功')
}
});
agoraRtc.enableAudio((ret) => {
if (ret.code == 0) {
//success
console.log('開(kāi)啟音頻成功---' + this.props.channel);
agoraRtc.joinChannel({
channel: this.props.channel,
uid: _userid
}, function (ret) {
if (ret.code == 0) {
console.log('加入頻道成功');
}
});
}
});
agoraRtc.remoteUserOfflineListener((ret) => {
api.toast({
msg: '對(duì)方已掛斷'
})
this.fnhangup();
});
},
fnerr_listener() {
var agoraRtc = api.require('agoraRtc');
agoraRtc.errorListener(function (ret) {
if (ret.errorCode == 0) {
var agoraRtc = api.require('agoraRtc');
agoraRtc.leaveChannel(function (ret) {
if (ret.code == 0) { //success
}
});
api.toast({
msg: '通話出錯(cuò)!'
});
}
});
},
fnhangup() {
var agoraRtc = api.require('agoraRtc');
agoraRtc.leaveChannel(function (ret) {
if (ret.code == 0) {
//success
}
});
this.data.connected = false;
}
}
};
</script>
<style>
.agorartc-call-voice_page {
height: 100%;
width: 100%;
background-color: #fff;
}
.agorartc-call-voice_list {
height: 64px;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
margin-bottom: 10px;
}
.agorartc-call-voice_userinfo {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
padding-left: 20px;
}
.agorartc-call-voice_callimg {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-end;
align-items: center;
flex-grow: 2;
padding-right: 20px;
}
.agorartc-call-voice_connected {
position: absolute;
top: 0;
left: 0;
background-color: #fff;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.agorartc-call-voice_hangup {
margin-top: 30px;
}
</style>avm.js 默認(rèn)使用 flex 彈性盒子布局,實(shí)現(xiàn)UI時(shí),應(yīng)充分利用 flex 彈性布局原理進(jìn)行布局。而實(shí)現(xiàn)聲網(wǎng)語(yǔ)音通話的核心邏輯很簡(jiǎn)單:兩個(gè)用戶加入同一個(gè)頻道即可 。
以上就是跨端開(kāi)發(fā)框架avm組件封裝經(jīng)驗(yàn)分享的詳細(xì)內(nèi)容,更多關(guān)于跨端開(kāi)發(fā)框架avm組件封裝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解JavaScript實(shí)現(xiàn)簡(jiǎn)單的詞法分析器示例
這篇文章主要為大家介紹了詳解JavaScript實(shí)現(xiàn)簡(jiǎn)單的詞法分析器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
JavaScript?API?ResizeObserver使用示例
這篇文章主要為大家介紹了JavaScript?API?ResizeObserver的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
ComponentLoader?與動(dòng)態(tài)組件實(shí)例詳解
這篇文章主要為大家介紹了ComponentLoader?與動(dòng)態(tài)組件實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Javascript調(diào)用XML制作連動(dòng)下拉列表框
Javascript調(diào)用XML制作連動(dòng)下拉列表框...2006-06-06

