首页 > 其他分享 >APICloud实战案例:如何封装AVM组件?(以声网组件为例)

APICloud实战案例:如何封装AVM组件?(以声网组件为例)

时间:2022-11-07 16:56:39浏览次数:101  
标签:flex APICloud ret AVM api stml 组件 agoraRtc

AVM.js(Application-View-Model)是一个移动优先的高性能跨端JavaScript框架,支持一次编写多端渲染。它提供更趋近于原生的编程体验,通过简洁的模型来分离应用的用户界面、业务逻辑和数据模型,适合高度定制的应用开发。

AVM前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架AVM.js以及多端统一编译工具,完全兼容Web Components标准,同时兼容Vue和React语法糖编写代码,编译工具将Vue和React相关语法糖编译转换为AVM.js代码。

有Vue和React开发经验的开发者很容易上手。

1. 组件的定义和引用

(1) 使用STML定义一个组件/页面

STML组件兼容Vue单文件组件(SFC)规范,使用语义化的HTML模板及对象化JS风格定义组件或页面。STML最终被编译为JS组件/页面,渲染到不同终端。

定义组件:

// 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>

(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的方式,这里以一个示例来进行说明。

定义子组件,在props里面注册一个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等。

(1) 在其它页面使用子组件时传递静态值:

// 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) 通过数据绑定传递动态值:

// 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>

传递静态值时只能传递字符串类型数据,通过数据绑定的方式则可以传递任意类型的数据。

3. 监听子组件事件

监听子组件事件和监听普通事件类似,如:

// 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>

以上示例中监听了子组件的result事件,子组件里面通过fire方法来触发监听的事件:

// 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方法有两个参数,第一个参数为事件名称,第二个参数为要传递的自定义数据,在父组件监听方法里面通过e.detail获取传递的数据。

// api-index.stml:

methods: {

onGetResult(e){

console.log(e.detail.msg);

}

}

4. 声网组件实例

了解了以上组件的规则和用法,就可以封装自己的组件了 。下面看一个基于agoraRtc声网模块,实现1对1语音通话的组件实例:

<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: "需要启用麦克风权限"

});

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;

}

});

// 多人语音通话 ,需设置角色为主播

agoraRtc.setClientRole({

role: 1

}, function (ret) {

if (ret.code == 0) {

//success

console.log('设置主播模式成功')

}

});

agoraRtc.enableAudio((ret) => {

if (ret.code == 0) {

//success

console.log('开启音频成功---' + 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: '对方已挂断'

})

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: '通话出错!'

});

}

});

},

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%;

 

}

.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;

 

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默认使用flex弹性盒子布局,实现UI时,应充分利用flex弹性布局原理进行布局。而实现声网语音通话的核心逻辑很简单:两个用户加入同一个频道即可。

立即体验:AVM.js框架

标签:flex,APICloud,ret,AVM,api,stml,组件,agoraRtc
From: https://www.cnblogs.com/kaifacss/p/16866513.html

相关文章

  • uniapp自定义组件的使用--记录
    在pages.json同级目录下创建目录和文件:components:  videoComp:VideoPlaySelf.vueVideoPlaySelf.vue内容<template><videoclass="video"id="myVideo"......
  • uniapp引入微信小程序自定义视频组件--记录
    官方文档:https://zh.uniapp.dcloud.io/tutorial/miniprogram-subject.html在pages.json同级目录下创建目录和文件:wxcomponents:   my-video-play:index.js ......
  • 2、DevExtreme 饼状图组件
    1、创建创建vue文件,引入dev基本组件importDxPieChart,{DxLegend,DxSeries,DxLabel,DxConnector,DxFont,}from'devextreme-vue/pie-chart'源码<!-......
  • 父组件访问子组件的方法或者data数据,经常出现访问失败的解决方案
    往往我们在开发项目时都经常用到$refs 来直接访问子组件的方法,但是这样调用的时候可能会导致数据的延迟滞后的问题,则会出现bug。解决方法则是推荐采取异步回调的方法,然......
  • 使用Web Component自定义组件
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="widt......
  • 组件之间的通信
    在vue开发中,组件通信尤为重要,特别是父子之间的组件通信一、父组件传递给子组件把父组件的信息,数据传给子组件,在子组件上面展示,这时候需要props即可完成二者之间的通......
  • vue在线预览word,excel , pdf组件化
    方法一:如果文件是域名的,可以使用微软免费接口//由于免费的在线查看,不支持ip+端口的形式所以单独处理this.dialog.url='http://view.officeapps.live.com/op/view.aspx?s......
  • React组件基础二
    1.注册事件React注册事件与DOM的事件语法非常像语法on+事件名={事件处理程序}比如onClick={this.handleClick}注意:React事件采用驼峰命名法,比如onMouseEnter,onClick......
  • Flutter 图表组件 charts_flutter_new
    Flutter图表插件charts_flutter_new前言也许你的项目中需要一个图标的插件,比如显示会员的消费情况。你可以看下charts_flutter_new这个插件是否合适。可以通过这......
  • 14-组件篇之消息队列(3)_ev
                                                   ......