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

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

1. 组件的定义和引用:

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>

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

定义子组件,在 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等。

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

封装 avm 组件经验分享的更多相关文章

  1. log4net日志组件经验分享

    引自log4net日志组件经验分享 我们在开发WEB项目的时候,经常会出现这样的情况:在本地调试都是正常的,但是部署到服务器上就不行了.一般出现这种情况很大一部分原因是因为服务的环境和本地不同,数据库 ...

  2. asp.net core封装layui组件示例分享

    用什么封装?自然是TagHelper啊,是啥?自己瞅文档去 在学习使用TagHelper的时候,最希望的就是能有个Demo能够让自己作为参考 怎么去封装一个组件? 不同的情况怎么去实现? 有没有更好更 ...

  3. 使用log4net日志组件经验分享

    常见步骤: 第一:在项目中引用log4net组件. 第二:配置log4net,一般都写在web.config中. 第三:调用部分.       具体怎么配置,大家可以参考博客其它博友写的,这里我只写我 ...

  4. 自己封装的一个JS分享组件

    因为工作的需求之前也封装过一个JS分享插件,集成了我们公司常用的几个分享平台. 但是总感觉之前的结构上很不理想,样式,行为揉成一起,心里想的做的完美,实际上总是很多的偏差,所以这次我对其进行了改版. ...

  5. (转)CMOS Sensor的调试经验分享

    CMOS Sensor的调试经验分享 我这里要介绍的就是CMOS摄像头的一些调试经验. 首先,要认识CMOS摄像头的结构.我们通常拿到的是集成封装好的模组,一般由三个部分组成:镜头.感应器和图像信号处 ...

  6. CMOS Sensor的调试经验分享

    转自:http://bbs.52rd.com/forum.php?mod=viewthread&tid=276351 CMOS Sensor的调试经验分享 我这里要介绍的就是CMOS摄像头的一 ...

  7. 安装程序添加iis的方法经验分享

    原文:安装程序添加iis的方法经验分享 网上有一些这样的方法,但我这里主要做一些对比和扩充 网上这方面的文章的岁数比较大,server 08R2和win7出来后,整理这方面的资料的文章没找到,所以这里 ...

  8. android平台短视频技术之 视频编辑的经验分享.

    android平台短视频技术之 视频编辑的经验分享. 提示一: 各位看官,这里分享的是视频编辑,即剪切/拼接/分离/合并/涂鸦/标记/叠加/滤镜等对视频的编辑操作.不是流媒体网络播放等功能,请注意. ...

  9. 封装bootstrap-treegrid组件

    封装bootstrap-treegrid组件   阅读目录 一.开源的treegrid 1.组件效果预览 2.组件开源地址 二.封装treegrid 1.组件封装的必要性 2.组件封装代码示例 3.封 ...

随机推荐

  1. 洛谷P4408 [NOI2003] 逃学的小孩 (树的直径)

    本题就是从c到a/b再到b/a距离的最大值,显然,a和b分别是树的直径的两个端点,先用两次dfs求出树的直径,再用一次dfs求出每个点到a的距离,最后再用一次dfs求出每个点到距离它较近的a/b的距离 ...

  2. OSS对象存储

    OSS对象存储 当项目以微服务搭建时,多个服务往往运行在多台服务器上,此时针对存储文件的获取和保存,难以确定具体的位置: 针对这个问题,一般有两个办法: 搭建独立的文件存储服务器,用 FastDFS等 ...

  3. KubeEdge 1.12版本发布,稳定性、安全性、可扩展性均带来大幅提升

    摘要:2022年9月29日,KubeEdge发布1.12版本.新版本新增多个增强功能,在扩展性.稳定性.安全性上均有大幅提升. 本文分享自华为云社区<KubeEdge 1.12版本发布,稳定性. ...

  4. 前端ajax发送post 请求 json格式 springMVC报错415

    如标题所示 后端填坑日记 在使用springMVC的时候发现 后端使用@RequestBody注解会报错415 不支持的媒体类型 相信很多小伙伴都遇到过或者正在面临这个报错 提示错误:The serv ...

  5. 齐博x1关于小程序个性源代码的说明

    系统默认推荐商家小程序使用通用型的源码,即框架套壳iframe形式的.这个灵活性更高.但如果有特殊需求的话,也可以设置个性源码,比如配合uni-app使用,针对不同的小程序就使用不同的uni-app风 ...

  6. Redis—问题(1)

    写在前面 Redis 是一种 NoSQL 数据库,包含多种数据结构.支持网络.基于内存.可选持久性的键值对存储数据库,在我们的日常开发中会经常使用 Redis 来解决许多问题,比如排行榜.消息队列系统 ...

  7. Python基础之面向对象:3、继承与派生

    面向对象 一.三大特征之继承 python三大特征: 封装.继承.多态 三者中继承最为核心,实际应用对,感受较为直观 封装和多态略微抽象 1.继承的概念 继承的含义: ​ 在现实生活中,继承表示人与人 ...

  8. 修改服务器ssh端口

    最近,访问公司虚拟机都需要通过堡垒机才能访问了,觉得麻烦.要想不受该规则限制,也有办法,可以通过修改虚拟机ssh端口解决. 下面做个介绍. 1. 通过堡垒机登录虚拟机 2. 修改虚拟机ssh端口 编辑 ...

  9. (译)TDD(测试驱动开发)的5个步骤

    原文:5 steps of test-driven development https://developer.ibm.com/articles/5-steps-of-test-driven-deve ...

  10. 【题解】CF631B Print Check

    题面传送门 解决思路: 首先考虑到,一个点最终的情况只有三种可能:不被染色,被行染色,被列染色. 若一个点同时被行.列染色多次,显示出的是最后一次被染色的结果.所以我们可以使用结构体,对每一行.每一列 ...