探索Vue小程序框架的底层原理

news2025/1/20 1:41:19

最近晚上有时间复盘之前研究小程序框架的相关内容,总结文章记录一下。

本篇文章主要介绍百度19年开源的Mars小程序开发框架,和Taro、mpvue、uniapp类似,都是编译型小程序框架,都是通过将 Vue 或 React 源码直接编译为小程序源码,实现小程序快速开发。我们来介绍一下其设计思路与原理。

Mars是什么?

Mars 是由 Vue 驱动的多端开发框架,其语法规范完全遵循 Vue,支持一套代码同时运行到百度小程序、微信小程序以及 H5 Web 端。Mars 诞生于搜索垂类产品对于小程序和 H5 Web 端相同的产品业务需求的场景下。从框架设计研发之初,就定位于解决小程序以及 H5 Web 端的复用和同构开发能力。

设计思路

Mars 框架的设计思路是将跨多端的应用拆分为逻辑层和视图层,逻辑层采用同一套核心运行时进行数据驱动以及生命周期管理,视图层使用同一套模板语法,经过编译转换为特定平台的视图语言。

考虑到学习成本、生态完善程度以及在多端上的扩展性、业务场景等原因,我们选择了 Vue 技术栈,采用 Vue 单文件组件和模板语法来书写组件代码,引入标准基础组件和 API 规范和标准生命周期规范。

在此开发规范之上,基于 Vue 的模板语法和基础组件来构建视图层,基于 Vue 数据驱动及标准生命周期规范来构建逻辑层,实现多端运行。框架总体原理图如下:

image.png

我们分别从模板、逻辑和数据来聊聊是如何编译的。

模板

我们先看一下Vue模板和小程序模板是如何书写的:

Vue模版如下:

<!--index.wxml-->
<template class="container">
    <view class="userinfo">
        <button v-if="!hasUserInfo&&canIUse" open-type="getUserInfo">获取头像昵称</button>
        <block v-else>  
            <image @tap="bindViewTap" class="userinfo-avatar" src=""/>
            <text class="userinfo-nickname">{{userInfo.nickName}}</text>
        </block>
    </view>
    <view class="usermotto">
        <text class="user-motto">{{motto}}</text>
    </view>
</template>

小程序的模版内容如下:

<!--index.wxml-->
<view class="container">
    <view class="userinfo">
        <button wx:if="{{!hasUserInfo&&canIUse}}" open-type="getUserInfo">获取头像昵称</button>
        <block wx:else>  
            <image bindtap="bindViewTap" class="userinfo-avatar" src=""/>
            <text class="userinfo-nickname">{{userInfo.nickName}}</text>
        </block>
    </view>
    <view class="usermotto">
        <text class="user-motto">{{motto}}</text>
    </view>
</view>

如果我们对比小程序和Vue模版,会发现他们与html语法是十分相似的。区别只在于标签上属性值的写法,相互之间通过编译是可以转化的。我们可以在编译阶段由Vue模版编译到小程序模版。

逻辑

我们先看一下小程序的逻辑和Vue的逻辑部分:

Vue逻辑如下:

<script>
    export default{
        data(){},
        methods:{
            bindViewTap(){},
            getUserInfo(){}
        },
        mounted(){}
    }
</script>

小程序的逻辑如下:

Page({
    data:{},
    bindViewTap: function(){},
    onLoad: function(){},
    getUserInfo: function(){}
})

逻辑部分,小程序与Vue在书写方式上有很大差异,他们的逻辑代码在各自的运行时中执行。并且逻辑部分用户书写的灵活度是很大的,没有办法通过编译将Vue的逻辑编译成小程序的逻辑去执行。

那该怎么办呢,我们不如换一种思路。Vue运行时和Vue组件的逻辑在生产中都是以JS代码执行的,在小程序提供的环境中是可以执行的。我们可以让Vue运行时也可以在小程序中执行,这样开发者编写的Vue逻辑代码也可以在小程序中执行了。

数据

数据部分是最简单的,因为数据是以JS对象的形式存在的,在小程序和Vue中是相同的。

原理

通过对视图、逻辑和数据这三个部分的分析,我们可以使用以下思路来使用Vue开发小程序。

首先将Vue template部分编译成小程序的模版,之后在小程序逻辑部分运行整个Vue的运行时,以及开发者编写的逻辑代码。最后Vue数据发生变化时同步给小程序,触发视图刷新。

image.png
我们需要在编译阶段产出 .wxml、.css、.js以及.json文件,在template部分需要将v-bind等语法转换成小程序使用的格式。样式内容则可以直接提取出来作为css文件。我们会在Vue中规定一个字段作为配置,这部分配置会提取出来作为.json文件。

而对于js部分,由于我们的逻辑执行在Vue中,因此只需要用到小程序的生命周期,在生命周期中执行Vue运行时以及业务逻辑代码就可以了。

例如,Vue单文件组件内容如下:

<template>
    <view class="home-wrap">
        <navigator :url="item.bookApi" v-for="(item,index) in bookList">
            <book :poster="item.poster"></book>
        </navigator>
    </view>
</template>
<script>
import Book from 'components/Book/index';
export default{
    config:{
        navigationBarTitleText: "标题"
    },
    data(){},
    components:{
        book:Book
    }
}
</script>
<style>
    .home-wrap{
        width:100vw;
        height:100vh;
    }
</style>

编译成小程序的组件内容如下:

<!--wxml模板内容-->
 <view class="home-wrap">
        <navigator url="{{item.bookApi}}" v-for="(item,index) in bookList">
            <book poster="{{item.poster}}" compId="{{ (compId ? compId : '$root') + ',0' }}"></book>
        </navigator>
</view>
 /*wxss样式内容*/
 .home-wrap{
        width:100vw;
        height:100vh;
    }
/*json配置内容*/
{
        "navigationBarTitleText": "标题",
        "usingComponents":{"book":"../../components/Book/index"}
},
//js逻辑内容
import {createPage} from "../../mars-core/index"
import Book from "../../components/Book/index.vue"
Page(createPage({
    data(){},
    components:{
        book:Book
    }
}))

为了执行Vue运行时以及业务逻辑代码,我们需要在小程序中创建Vue实例,Vue在生产环境中是以JS代码来运行的。因此我们可以直接将Vue引入,然后在小程序onLoad阶段new一个Vue实例出来。

import Vue from 'vue'

Page({
    onLoad(){
        const vm = new Vue(options)
        this.$vue = vm
    }
})

但是要注意,Vue正常是要执行在浏览器中的,在执行时会进行DOM操作完成页面渲染,在小程序中我们需要将Vue进行DOM操作的部分删掉。做到这里模版已经有了,样式也有了,创建了Vue实例后逻辑也可以执行了,但到目前为止,小程序与Vue也没有真正联系上。

通过之前的分析我们了解到,小程序与Vue之间是通过数据来联系的,Vue中执行逻辑,修改数据,将数据变化同步给小程序,触发试图更新。因此,我们现在要做的就是在每次Vue中更新视图时,把数据修改同步给小程序,那么如何知道Vue中的逻辑执行造成了视图刷新了呢?

我们可以使用Vue的updated钩子函数。

const vueMixin = {
    updated(){
        setData(vm,this)
    }
}

updated钩子函数会在数据发生变化导致视图刷新后触发。我们可以在其中调用小程序的setData方法,来将变化后的数据同步给小程序,现在我们在Vue和小程序之间建立了联系。但这个联系还是单向的,Vue的数据变化可以修改小程序的视图。但小程序中用户的操作还不能传递给Vue进行处理。用户的操作体现在tap等事件中,由于我们所有的逻辑都在Vue中,因此需要让Vue接管小程序的事件处理。

我们可以在小程序的模版中去设置一个代理函数handleProxy,在这个事件代理函数中,调用Vue实例中的事件处理函数,触发开发者编写的业务处理逻辑。这样用户的操作通过事件代理传递给Vue进行处理,Vue处理过程中会修改数据,触发VirtualDom的更新,VirtualDom更新后会触发updated钩子函数,我们在updated钩子函数中将数据变化同步给小程序,使得小程序视图更新,完成了整个用户操作响应流程。

现在我们已经完成了Vue与小程序结合的整体结构,视图绘制发生在小程序中,业务逻辑运行在Vue中,小程序与Vue用事件和数据来进行通信。

组件机制原理也是一样的,视图依旧由小程序组件来绘制,业务逻辑运行在Vue组件中,小程序组件与Vue组件通过事件和数据来进行通信。

但是这么做的前提是我们需要将小程序组件与Vue组件关联起来,在我们创建Vue实例时有两种选择,一种是我们只在小程序根组件也就是Page中去创建Vue实例,Vue会继续创建组件实例。

image.png

在这种情况下小程序组件和Vue组件的创建分别是同时进行的,那么我们就需要将小程序组件与Vue组件之间进行关联匹配,否则他们之间的通信也就无从谈起了。

那么如何匹配呢?我们可以给每个组件都标记一个唯一的ID,然后通过ID来进行匹配。标记的方法就是从根组件开始,将根组件标记为 r o o t ,那么它的子组件就是 root,那么它的子组件就是 root,那么它的子组件就是root.0,$root.1等,不同层级间使用.来分割,其中列表循环特殊对待,我们使用横线来标记循环项。

例如root.1中有一个循环列表,这个循环列表中渲染了一个组件这个组件自身ID位root.1.0,然后循环产生的第一个子组件就是root.1.0-0,第二个就是root.1.0-1,这样我们通过ID给每个组件增加了标记,将相同ID的小程序组件与Vue组件匹配在一起。

另一种是我们去掉Vue创建组件实例的逻辑,自己在每个小程序组件创建时new一个Vue实例,但如果这么做,我们需要自己维护Vue各个实例间的父子关系。

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1293481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于FPGA的温度控制系统设计(论文+源码)

1.系统设计 本次基于FPGA的智能温度控制系统&#xff0c;以FPGA为控制核心&#xff0c;采用自顶向下的设计方法&#xff0c;按照模块化设计的思路分别实现各个模块&#xff0c;再加以整合实现整个系统&#xff0c;从而达到了温度控制的目的。系统以水箱为被控对象&#xff0c;…

深入探索C语言中的二叉树:数据结构之旅

引言 在计算机科学领域&#xff0c;数据结构是基础中的基础。在众多数据结构中&#xff0c;二叉树因其在各种操作中的高效性而脱颖而出。二叉树是一种特殊的树形结构&#xff0c;每个节点最多有两个子节点&#xff1a;左子节点和右子节点。这种结构使得搜索、插入、删除等操作…

《机器学习实战》MNIST 数据集的导入方法

1、在网上下载数据集 mnister 数据集有两个类型&#xff0c; &#xff08;1&#xff09;一个是手写的阿拉伯数字图片&#xff1a;MNIST 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1dd-I-laysPbT8wxbyvxTvg 提取码&#xff1a;1234 &#xff08;2…

深度解析 Kafka 消息保证机制

Kafka作为分布式流处理平台的重要组成部分&#xff0c;其消息保证机制是保障数据可靠性、一致性和顺序性的核心。在本文中&#xff0c;将深入探讨Kafka的消息保证机制&#xff0c;并通过丰富的示例代码展示其在实际应用中的强大功能。 生产者端消息保证 1 At Most Once &quo…

Android 13 Settings蓝牙列表卡顿问题排查及优化过程

一.背景 此问题是蓝牙列表界面息屏后再点击亮屏蓝牙界面卡住,划不动也不能返回,在人多的时候(附近开启的蓝牙设备过多的时候)会卡住大概四五秒才能滑动. 优化前效果见资源: 二.查找耗时点 根据Android Studio的Profiler工具进行排查,查找主线程时间线比较长的方法,如下:…

记录 | centos源码编译bazel

tensorflow的源码编译依赖于 bazel 这里进行 bazel 的源码编译 1、安装依赖 sudo yum install -y java-11-openjdk sudo yum install -y java-11-openjdk-devel sudo yum install -y protobuf-compiler zip unzip2、知悉要安装的 bazel 的版本 务必安装受支持的 Bazel 版本…

展望2024年供应链安全

2023年是开展供应链安全&#xff0c;尤其是开源治理如火如荼的一年&#xff0c;开源治理是供应链安全最重要的一个方面&#xff0c;所以我们从开源治理谈起。我们先回顾一下2023的开源治理情况。我们从信通院《2023年中国企业开源治理全景观察》发布的信息。信通院调研了来自七…

linux安装mysql5.7(一遍过)

之前安装的时候遇到了很多问题&#xff0c;浪费了一些时间。整理出这份教程&#xff0c;照着做基本一遍过。 这是安装包: 链接&#xff1a;https://pan.baidu.com/s/1gBuQBjA4R5qRYZKPKN3uXw?pwd1nuz 1.下载安装包&#xff0c;上传到linux。我这里就放到downloads目录下面…

软著项目推荐 疫情数据分析与3D可视化 - python 大数据

文章目录 0 前言1 课题背景2 实现效果3 设计原理4 部分代码5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据全国疫情数据分析与3D可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff0…

Google Bard vs. ChatGPT 4.0:文献检索、文献推荐功能对比

在这篇博客中&#xff0c;我们将探讨和比较四个不同的人工智能模型——ChatGPT 3.5、ChatGPT 4.0、ChatGPT 4.0插件和Google Bard。我们将通过三个问题的测试结果来评估它们在处理特定任务时的效能和响应速度。 导航 问题 1: 统计自Vehicle Routing Problem (VRP)第一篇文章发…

【Flink系列二】如何计算Job并行度及slots数量

接上文的问题 并行的任务&#xff0c;需要占用多少slot &#xff1f;一个流处理程序&#xff0c;需要包含多少个任务 首先明确一下概念 slot&#xff1a;TM上分配资源的最小单元&#xff0c;它代表的是资源&#xff08;比如1G内存&#xff0c;而非线程的概念&#xff0c;好多…

设备制造行业CRM:提升客户满意度,驱动业务增长

设备制造行业客户需求多样化、服务链路长&#xff0c;企业在关注APS、EMS等工业软件之余还要以客户为中心&#xff0c;做好客户服务。设备制造行业CRM管理系统是企业管理客户关系的利器&#xff0c;设备制造行业CRM的作用有哪些&#xff1f;一文带您看懂。 设备制造行业需要解…

【深度学习】强化学习(一)强化学习定义

文章目录 一、强化学习问题1、交互的对象1. 智能体&#xff08;Agent&#xff09;2. 环境&#xff08;Environment&#xff09; 2、强化学习的基本要素1. 状态 &#x1d460;2. 动作 &#x1d44e;3. 策略 &#x1d70b;(&#x1d44e;|&#x1d460;)4. 状态转移概率 &#x1…

elk(filebeat)日志收集工具

elk&#xff08;filebeat&#xff09;日志收集工具 elk&#xff1a;filebeat日志收集工具 和logstash相同 filebeat是一个轻量级的日志收集工具&#xff0c;所使用的系统资源比logstash部署和启动时使用的资源要小得多 filebeat可以运行在非Java环境。他可以代理logstash在…

ArcGIS Pro中怎么设置标注换行

在ArcGIS Pro中进行文字标注的时候&#xff0c;如果标注的字段内容太长&#xff0c;直接标注的话会不美观&#xff0c;而且还会影响旁边的标注显示&#xff0c;这里为大家介绍一下在ArcGIS Pro中设置文字换行的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的…

【UE5】瞬移+马赛克过渡效果

效果 步骤 1. 新建一个工程&#xff0c;创建一个Basic关卡 2. 添加第三人称游戏资源到内容浏览器 3. 新建一个材质&#xff0c;这里命名为“M_Pixel” 打开“M_Pixel”&#xff0c;设置材质域为“后期处理” 在材质图表中添加如下节点 此时效果如下&#xff0c;已经有马赛克的…

JVM 命令行监控及诊断工具

面试题 你使用过Java虚拟机性能监控和故障处理工具吗&#xff1f;&#xff08;美图&#xff09; 怎么打出线程栈信息。&#xff08;字节跳动&#xff09; JVM诊断调优工具用过哪些&#xff1f; (京东) 怎么获取 Java 程序使用的内存&#xff1f;堆使用…

Django模板,Django中间件,ORM操作(pymysql + SQL语句),连接池,session和cookie, 缓存

day04 django进阶-知识点 今日概要&#xff1a; 模板中间件ORM操作&#xff08;pymysql SQL语句&#xff09;session和cookie缓存&#xff08;很多种方式&#xff09; 内容回顾 请求周期 路由系统 最基本路由关系动态路由&#xff08;含正则&#xff09;路由分发不同的app中…

ssh安装和Gitee(码云)源码拉取

文章目录 安装ssh服务注册码云公钥设置码云账户SSH公钥安装git客户端和git-lfs源码获取 安装ssh服务 更新软件源&#xff1a; sudo apt-get update安装ssh服务 sudo apt-get install openssh-server检查ssh是否安装成功 which ssh输出&#xff1a; /usr/bin/ssh启动ssh 服…

『亚马逊云科技产品测评』活动征文|基于亚马逊云EC2搭建PG开源数据库

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器&#xff08;Elastic Compute Cloud&#xff09;是亚马…