我是一首歌。 放弃很容易,坚持一定很酷。 陌陌公众号关注后端歌曲,获取后端知识。
本文将介绍Taro如何从一个旨在解决小程序开发问题的框架演变为多端统一开发框架。
使用React句型写小程序网站变为小程序,谈小程序开发
陌陌小程序为我们的业务提供了新的诠释形式,但对于开发者来说,开发体验却变得不那么友好了。
首先,从文件组织的角度来看,一个小程序页面或组件需要同时包含4个文件:脚本逻辑、样式、模板和配置文件。 当开发一个功能模块时,需要在4个文件之间切换,而当功能模块较多时,需要在多个文件之间切换,非常浪费时间。
其次,从开发方式来看,在后端工程思想深入人心的当今世界,小程序的各种开发方式变得有些落后,主要体现在以下几个方面:
因此,从开发方式来看,小程序开发还没有融入当前主流的工程开发思路。 很多行业发展模式和工具在小程序开发中还没有得到相应的展现,比如从后端工业时代回到刀耕火种时代。 。
最后,从代码规范来看,小程序规范存在很多不一致的地方。 例如,外部组件的属性名称有时全部大写,有时采用驼峰格式,有时采用虚线格式。 这意味着在编码时,你必须不时查阅文档以确定编写方法。
如何更高尚地开展好友计划
在 Taro 设计之初,我们的观点是希望用一种更高尚的方式来开放闺蜜程序,解决小程序开发中的各种痛点。 首先,我们希望采用后端工程化的方式进行开发。 同时,在句型方面,我们希望抛弃小程序四种不同的句型,遵循一套熟悉的框架句型进行开发。 这样不仅可以更好地保证开发质量、提升开发体验,而且还可以大大减少语句数量。 开发人员运行最好的朋友程序的成本。
因此,在开发方式上,Taro 构建了一套编译工具,并引入了后编译机制,可以手动对源文件进行一系列处理,最终输出小程序上的可执行文件,包括代码。 编译转换处理、添加文件预处理功能、支持npm包管理等。这部分的原理将在后续章节中给大家介绍。 句型标准方面,我们重点关注了市场上流行的三种后端框架。
React、Vue、Angular是目前三大后端框架。 他们每个人都有自己的风格。 关于它们的优点,业界仍然存在无休止的争论。 这是智者仁者见仁智者见智的问题,本文不予讨论。 再评论一下。 Taro最终采用React句型作为自己的句型标准,主要有以下几个原因:
最终,Taro 采用了 React 句型作为自己的句型标准,并与后端工程化的思想相结合,为小程序开发打造了更加高贵的开发体验。
如何获得贵族地位
那么如何使用React来打开好友程序呢? Taro采用了编译原理的思想。 所谓编译原理就是对输入源代码的句型进行分析,建立句型树网站变为小程序,然后对句型树进行转换再解析生成目标代码的过程。
探索多种可能性
多端统一开发仍然是所有开发者的共同追求。 在终端碎片化的背景下,过去推出了Hybrid模式,后来ReactNative和Weex风起云涌,现在Flutter诞生了。 所有这些都是为了能够一次编写、到处运行。 各个终端单独开发的成本较高,因此一种能够尽可能平滑多终端开发差异的开发方案就变得极其重要。
多端转换原理
在开发过程中,我们遵循React句型标准,结合编译原理的思想,对代码文件进行一系列的转换操作,最终得到可以在小程序中运行的代码。 React 最初是为了解决 Web 开发问题而创建的,所以只需对代码稍作修改,就可以直接生成在 Web 端运行的代码,而同样属于 React 语句结构的 ReactNative 可以轻松提供支持。 同理,对于其他平台,如快应用、百度小程序等,如果将源代码进行编译转换,也可以获得该平台下对应的句型代码。
消除许多差异
基于编译原理,我们已经能够将Taro源代码编译成可以在不同终端上运行的代码。 然而,这对于实现多终端发展还远远不够。 由于不同的平台有各自的特点,所以每个平台都是不同的。 这种差异主要体现在组件标准不同、API标准不同、运行机制不同。
可见,小程序和Web上的组件标准和API标准存在很大差异。 这种差异很难仅通过代码编译来消除。 例如,你不能直接将小程序编译成
这套标准主要由标准运行框架、标准基础组件库、标准端能力API三部分组成。 运行时框架和API对应@taro/taro,组件库对应@tarojs/components。 不同端执行该标准,以达到差异化的目的。
在标准定制方面,我们原本想重新定制一套标准规范,发现在所有终端上实现这套标准成本太高,所以我们思考为什么不使用一个终端的组件库和API作为标准。 呢绒? 这不仅节省了标准定制的时间,而且我们也不必为此去执行这套标准。 最终,在所有终端中,我们选择了陌陌小程序的组件库和API作为Taro的运行标准。 因为陌陌小程序的文档是专门建立的,而且组件和API也非常丰富,最重要的是,百度小程序和支付宝小程序都遵循陌陌小程序的标准。 这样一来,Taro实现这两个平台转换的成本就大大降低了。
运行
本文介绍了Taro编译成小程序并运行H5时发生的情况。
Momo小程序模板JSX转换的实现
以这段代码为例:
import Taro, { Component } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
class Home extends Component {
config = {
navigationBarTitleText: '首页'
}
state = {
numbers: [1, 2, 3, 4, 5]
}
handleClick = () => {
this.props.onTest()
}
render () {
const oddNumbers = this.state.numbers.filter(number => number & 2)
return (
奇数:
{
oddNumbers.map(number => {number})
}
偶数:
{
numbers.map(number => number % 2 === 0 &&
{number})
}
)
}
}
Taro的结构主要分为两个方面:运行时和编译时。 运行时负责在相应的无法运行的环境中运行编译后的代码。 你可以将Taro运行时理解为后端开发中的polyfill。 例如,小程序创建新页面时,使用Page方法传入文字对象,不支持使用类。 如果全靠编译时,那么我们要做的就是粗略地将类转换为对象,将状态变为数据,将componentDidMount等生命周期转换为onReady,将可能的类函数(Classmethod)和类属性函数。 (Classpropertyfunction)转化为文字对象模式(Objectpropertyfunction)等等。
但这可能会让我们的编译时工作变得非常复杂,当一个类极其复杂时出错的概率就会增加。 但我们有更好的方法:实现一个createPage方法,接受一个类作为参数,返回小程序Page方法所需的文字对象。 除了简化编译工作之外,我们还可以在createPage中对编译时生成的类进行各种操作和优化。 将运行时的工作分开后,我们只需要在编译时在文件顶部添加一行代码Page(createPage(componentName))即可。
如果你从TaroCLI的dist文件夹中查看编译后的代码,你会发现它相当复杂。 那是因为代码会通过babel编译成ES5。
小程序除了Page类型之外,还有Component类型,所以Taro似乎也有createComponent的技能。 因为Component是小程序中的全局变量,所以我们要把导入的Component重命名为{Component}from'@tarojs/taro'。
回到代码的开头,我们定义了一个类属性config。 config是一个对象表达式(ObjectExpression)。 该对象表达式只接受通配符作为标识符(Identifiers)或字符串,并且键值只能是基本类型。 在这种简单的情况下,我们只需要将这个对象表达式转换为 JSON 即可。 另外一个类属性state,有点像Page中小程序的数据,但大多数情况下并不是完整的数据(数据会在下面进一步讨论)。 这里我们不需要做太多,babel的插件transform-class-proerties会将其编译到类构造函数中。 我们将函数handleClick留给运行时来处理。 感兴趣的朋友可以跳转到Taro运行时原理查看具体技术细节。
让我们再次看看我们的 render() 函数。 它的第一行代码通过filter过滤掉数字列表中的所有素数。 实际用于循环的是oddNumbers,而oddNumbers并不在this.state中,所以我们必须自动将其添加到this.state中。 与React一样,Taro每次更新时也会调用render函数,但与React不同的是,React的render是一种创建虚拟DOM的方式,而Taro的render会更名为_createData,这是一种创建数据的方式。 方法:JSX中使用的数据在这里创建,最后放到小程序Page或者Component鞋工厂方法中。 最终我们的渲染方法将被编译为:
_createData() {
this.__state = arguments[0] || this.state || {};
this.__props = arguments[1] || this.props || {};
const oddNumbers = this.__state.numbers.filter(number => number & 2);
Object.assign(this.__state, {
oddNumbers: oddNumbers
});
return this.__state;
}
开发指南中引入目录时,如果不在这个模块文件下,就不要使用相对路径,而是使用绝对路径。
如果是js 文件的引入,是和mgr 项目一样的,@/ 代表根目录 如果是 scss 文件的引入,styles 文件也做了 alias,引入的时候 `@import "~@/styles/variables.scss"`
编写scss时,先引入变量文件,统一使用定义的颜色字体。 必须读取 /variables.scss 文件一次。
我是一首歌谣 放弃很容易 坚持一定很酷