博客列表 >APICloud中封装AVM组件经验分享

APICloud中封装AVM组件经验分享

YonMaker生态定制
YonMaker生态定制原创
2022年10月13日 16:22:37450浏览

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组件/页面,渲染到不同终端。

定义组件:

  1. // api-test.stml:
  2. <template>
  3. <view class='header'>
  4. <text>{this.data.title}</text>
  5. </view>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'api-test',
  10. data(){
  11. return {
  12. title: 'Hello APP'
  13. }
  14. }
  15. }
  16. </script>
  17. <style scoped>
  18. .header{
  19. height: 45px;
  20. }
  21. </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) 在其它页面使用子组件时传递静态值:

  1. // app-index.stml:
  2. <template>
  3. <view>
  4. <api-test title="Hello App!"></api-test>
  5. </view>
  6. </template>
  7. <script>
  8. import './components/api-test.stml'
  9. export default {
  10. name: 'app-index'
  11. }
  12. </script>

(2) 通过数据绑定传递动态值:

  1. // app-index.stml:
  2. <template>
  3. <view>
  4. <api-test v-bind:title="msg"></api-test>
  5. </view>
  6. </template>
  7. <script>
  8. import './components/api-test.stml'
  9. export default {
  10. name: 'app-index',
  11. data() {
  12. return {
  13. msg: 'Hello App!'
  14. }
  15. }
  16. }
  17. </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语音通话的组件实例:

  1. <template>
  2. <view class="agorartc-call-voice_page">
  3. <safe-area></safe-area>
  4. <view class="agorartc-call-voice_list" v-for="(item,index) in userList">
  5. <view class="agorartc-call-voice_userinfo">
  6. <image class="agorartc-call-voice_userinfo-image" thumbnail='false'
  7. style="width: 64px; height: 64px; margin-right:10px" src={{item.userimg }}></image>
  8. <text class="agorartc-call-voice_userinfo-text">{{item.username }}</text>
  9. </view>
  10. <view class="agorartc-call-voice_callimg">
  11. <image @click="fnstart_voice_call(item.userid)" thumbnail='false' style="width: 50px; height: 50px"
  12. src="../../image/voice-call.png"></image>
  13. </view>
  14. </view>
  15. <view class="agorartc-call-voice_connected" v-if="connected">
  16. <image class="agorartc-call-voice_voice" thumbnail='false' style="width: 200px;"
  17. src="../../image/video-voice.gif"></image>
  18. <image class="agorartc-call-voice_hangup" @click="fnhangup()" thumbnail='false'
  19. style="width: 64px; height: 64px;" src="../../image/video-hangup.png"></image>
  20. </view>
  21. </view>
  22. </template>
  23. <script>
  24. export default {
  25. name: 'agorartc-call-voice',
  26. props: {
  27. channel: String,
  28. userList: Array,
  29. rtcAppId: String
  30. },
  31. installed() {
  32. this.fnishasper_mic();
  33. },
  34. data() {
  35. return {
  36. connected: false
  37. };
  38. },
  39. methods: {
  40. fnishasper_mic(_userid) {
  41. var resultList = api.hasPermission({
  42. list: ["microphone"]
  43. });
  44. if (resultList[0].granted) {
  45. } else {
  46. api.toast({
  47. msg: "需要启用麦克风权限"
  48. });
  49. api.requestPermission({
  50. list: ["microphone"]
  51. }, res => {
  52. if (res.list[0].granted) {
  53. }
  54. });
  55. }
  56. },
  57. fnstart_voice_call(_userid) {
  58. this.fnrtc_init();
  59. this.fnerr_listener();
  60. this.fnjoin_channel(_userid);
  61. },
  62. fnrtc_init() {
  63. console.log('初始化');
  64. var agoraRtc = api.require('agoraRtc');
  65. agoraRtc.init({
  66. appId: this.props.rtcAppId
  67. });
  68. },
  69. fnjoin_channel(_userid) {
  70. console.log('121:---' + _userid);
  71. this.data.connected = true;
  72. var agoraRtc = api.require('agoraRtc');
  73. agoraRtc.joinChannelSuccessListener(function (ret) {
  74. console.log(ret.uid + 'uid------');
  75. });
  76. agoraRtc.remoteUserJoinedListener((ret) => {
  77. console.log(ret.uid + 'remoteUserJoinedListener------');
  78. if (ret.uid) {
  79. this.data.connected = true;
  80. }
  81. });
  82. // 多人语音通话 ,需设置角色为主播
  83. agoraRtc.setClientRole({
  84. role: 1
  85. }, function (ret) {
  86. if (ret.code == 0) {
  87. //success
  88. console.log('设置主播模式成功')
  89. }
  90. });
  91. agoraRtc.enableAudio((ret) => {
  92. if (ret.code == 0) {
  93. //success
  94. console.log('开启音频成功---' + this.props.channel);
  95. agoraRtc.joinChannel({
  96. channel: this.props.channel,
  97. uid: _userid
  98. }, function (ret) {
  99. if (ret.code == 0) {
  100. console.log('加入频道成功');
  101. }
  102. });
  103. }
  104. });
  105. agoraRtc.remoteUserOfflineListener((ret) => {
  106. api.toast({
  107. msg: '对方已挂断'
  108. })
  109. this.fnhangup();
  110. });
  111. },
  112. fnerr_listener() {
  113. var agoraRtc = api.require('agoraRtc');
  114. agoraRtc.errorListener(function (ret) {
  115. if (ret.errorCode == 0) {
  116. var agoraRtc = api.require('agoraRtc');
  117. agoraRtc.leaveChannel(function (ret) {
  118. if (ret.code == 0) { //success
  119. }
  120. });
  121. api.toast({
  122. msg: '通话出错!'
  123. });
  124. }
  125. });
  126. },
  127. fnhangup() {
  128. var agoraRtc = api.require('agoraRtc');
  129. agoraRtc.leaveChannel(function (ret) {
  130. if (ret.code == 0) {
  131. //success
  132. }
  133. });
  134. this.data.connected = false;
  135. }
  136. }
  137. };
  138. </script>
  139. <style>
  140. .agorartc-call-voice_page {
  141. height: 100%;
  142. width: 100%;
  143. background-color: #fff;
  144. }
  145. .agorartc-call-voice_list {
  146. height: 64px;
  147. width: 100%;
  148. display: flex;
  149. flex-direction: row;
  150. flex-wrap: nowrap;
  151. justify-content: flex-start;
  152. margin-bottom: 10px;
  153. }
  154. .agorartc-call-voice_userinfo {
  155. display: flex;
  156. flex-direction: row;
  157. flex-wrap: nowrap;
  158. justify-content: flex-start;
  159. align-items: center;
  160. padding-left: 20px;
  161. }
  162. .agorartc-call-voice_callimg {
  163. display: flex;
  164. flex-direction: row;
  165. flex-wrap: nowrap;
  166. justify-content: flex-end;
  167. align-items: center;
  168. flex-grow: 2;
  169. padding-right: 20px;
  170. }
  171. .agorartc-call-voice_connected {
  172. position: absolute;
  173. top: 0;
  174. left: 0;
  175. background-color: #fff;
  176. width: 100%;
  177. height: 100%;
  178. display: flex;
  179. flex-direction: column;
  180. justify-content: space-around;
  181. align-items: center;
  182. }
  183. .agorartc-call-voice_hangup {
  184. margin-top: 30px;
  185. }
  186. </style>

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


如果您想用YonBuilder / APICloud技术定制软件应用,可联系vx:yonyou898

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议