跨端开发框架avm组件封装经验分享

目录
  • 引言
  • 1. 组件的定义和引用:
    • 1.1 使用stml定义一个组件 / 页面
    • 1.2 组件引用:
  • 2. 向子组件传值
    • 2.1 在其它页面使用子组件时传递静态值:
    • 2.2 通过数据绑定传递动态值:
  • 3. 监听子组件事件**
  • 4.  声网组件实例

引言

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组件封装经验分享的详细内容,更多关于跨端开发框架avm组件封装的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue3+ElementPlus 表单组件的封装实例

    目录 form文件夹 FormItem.tsx 在页面中引用 总结 在系统中,表单作为用户与后端交互的重要传递组件使用频率极高,故对其进行封装是必然的,也是一个编写规范代码的前端程序员必须做的一件事. 在Vue3中封装组件时,能感受到与Vue2有着很大的不同,故作此记录. form文件夹 FormItem.tsx文件是Typescript中的新特性之一,详细可查阅TS中文文档 index.vue是主体文件 type.ts表单的规约 FormItem.tsx import filter from

  • vue如何使用vue slot封装公共组件

    目录 使用vue slot封装公共组件 使用slot插槽封装 使用vue slot封装公共组件 公用子组件:publicSlot       <div>         <div class="top">         <h1 class="title">{{title}}</h1>             <slot name="headerRight"> 可以根据你slot nam

  • 在vue3.0中封装button使用slot组件

    目录 封装button使用slot组件 需求 子组件 父组件引用 vue带你封装一个button 创建一个 ShowButton.vue 的组件 新建一个 Button.vue ShowButton.vue 内使用 封装button使用slot组件 需求 同一个button在不同页面使用,只有文字不一样;有的内容为登录有的为注册 下面我们自封一个button组件 子组件 <template> <!-- :type="type" 为按钮类型 :disabled=&quo

  • vue中封装echarts公共组件过程

    目录 1.安装echarts 2.在mian.js中全局引入 3.下面开始封装图表 4.接下来只需要在需要显示图表的地方引入Echart.vue 定义图表公共样式是为了统一同一网站各页面图表的基础样式baseOption.js(轴线.区域.色系.字体),统一封装后页面需要直接引入,传入所需参即可覆盖基础样式. 以下示例封装图表组件Echart.vue. 1.安装echarts npm install echarts --save npm install lodash --save // 若已安装

  • 跨端开发框架avm组件封装经验分享

    目录 引言 1. 组件的定义和引用: 1.1 使用stml定义一个组件 / 页面 1.2 组件引用: 2. 向子组件传值 2.1 在其它页面使用子组件时传递静态值: 2.2 通过数据绑定传递动态值: 3. 监听子组件事件** 4.  声网组件实例 引言 avm.js 是一个跨端开发框架,AVM(Application-View-Model)前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架avm.js以及多端统一编译工具,完全兼容Web

  • 移动端滑动切换组件封装 vue-swiper-router实例详解

    具体代码如下所述: <strong>组件部分</strong> <template> <div class="main"> <div class="page-tab"> <div :class="nowPath == item.path ? 'tab-item tab-item_active' : 'tab-item'" v-for='(item, index) in tabLis

  • vue-image-crop基于Vue的移动端图片裁剪组件示例

    本文介绍了vue-image-crop基于Vue的移动端图片裁剪组件示例,分享给大家,具体如下: 代码地址:https://github.com/jczzq/vue-image-crop vue-image-crop 基于Vue的移动端图片裁剪组件 组件使用URL.createObjectURL()等新特性,使用前注意兼容问题.IE >= 10 注意:该组件适用于 PC 端,不推荐手机端使用. 功能预览 快速开始 安装Node >= 8.9.0(推荐LTS = 8.11.0) # 安装 vue

  • MYSQL跨服务器同步数据经验分享

    项目需要,自己找了些资料和亲手配置过后:得出的经验分享. (1)主服务器 修改配置文件/etc/my.cnf(my.ini) [mysqld] # mysql-bin是log文件的前缀,也可以使用其它的名字,比如服务器名 # 如果不带路径,会把log文件写到`/var/lib/mysql`下 log-bin=mysql-bin # serverid在一个同步体系中必须是唯一的,大于等于1且小于2^32-1的整数 server-id=1 binlog-do-db = 数据库名 (你要备份的数据库)

  • 使用bootstrap validator的remote验证代码经验分享(推荐)

    这里需要说一下,bootstrapvalidator的帮助文档写的比较简单,对于remote验证器的说明更是如此,在经历多方测试之后才明白如何使用这个验证器. 一个典型的ajax验证代码如下: 服务端验证代码(使用spring mvc)如下: /* * 返回String类型的结果 * 检查用户名的合法性,如果用户已经存在,返回false,否则返回true(返回json数据,格式为{"valid",true}) */ @RequestMapping(value = "/chec

  • JS组件系列之JS组件封装过程详解

    前言: 之前分享了那么多bootstrap组件的使用经验,这篇文章打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一个$("#id").MyJsControl({})做我们自己的组件,我们该如何去做呢,别急,我们慢慢来看看过程. 一.扩展已经存在的组件 1.需求背景 很多时候,我们使用jquery.ajax的方式向后台发送请求,型如 $.ajax({ type: "post", u

  • JS 组件系列之 bootstrap treegrid 组件封装过程

    正文 前言:最近产品需要设计一套相对完整的组织架构的解决方案,由于组织架构涉及到层级关系,在表格里面展示层级关系,自然就要用到所谓的treegrid.可惜的是,一些轻量级的表格组件本身并没有自带树形表格的功能,比如bootstrapTable就没有这个功能,怎么办呢?如果是jqgrid.easyUI的表格,treegrid的效果可以说是轻而易举就能解决,而项目目前用的就是bootstrapTable,不可能这个时候因为这个需求去换组件吧.博主分析了下,无非就两种解决方案:一种就是扩展bootst

  • Java异常区分和处理的一些经验分享

    异常处理的一些经验总结 这篇文章主要是对Java异常选择和使用中的一些误区的总结和归纳,希望各位读者能够熟练掌握异常处理的一些注意点和原则.只有处理好了异常,才能提升开发人员的基本素养,提高系统的健壮性,提升用户体验,提高产品的价值.废话少说,直接看: 误区一.异常的选择 这张图描述了异常的结构,其实我们都知道异常分检测异常和非检测异常,但是在实际中又混淆了这两种异常的应用.由于非检测异常使用方便,很多开发人员就认为检测异常没什么用处.其实异常的应用情景可以概括为以下: 1.调用代码不能继续执行

  • PHP服务端环境搭建的图文教程(分享)

    一.PHP服务端环境搭建 1.php 服务端环境 安装套件 xampp(apach+mysql+php解释器) F:\MyDoc文件(重要)\DL_学习\download重要资源\apache服务器组件 安装 此时进入xmapp面板显示成功运行 测试本地Apache服务器是否开启:浏览器中输入127.0.0.1 回车即可进入xmapp官网 4.修改浏览器中默认出现的dashboard文件夹 打开xmapp下htdocs文件夹下 index.php文件 配置文件中默认跳转到本文件夹 解决办法:将h

  • 基于Vue的移动端图片裁剪组件功能

    最近项目上要做一个车牌识别的功能.本来以为很简单,只需要将图片扔给后台就可以了,但是经测试后识别率只有20-40%.因此产品建议拍摄图片后,可以对图片进行拖拽和缩放,然后裁剪车牌部分上传给后台来提高识别率.刚开始的话还是百度了一下看看有没有现成的组件,但是找来找去都没有找到一个合适的,还好这个功能不是很着急,因此自己周末就在家里研究一下. Demo地址:https://vivialex.github.io/demo/imageClipper/index.html 下载地址:https://git

随机推荐