Blogger Information
Blog 10
fans 0
comment 0
visits 4349
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
APICloud中封装AVM组件经验分享
YonMaker生态定制
Original
456 people have browsed it

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

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post