写给跨端玩家:支撑淘宝上亿日活的跨端框架—— Rax 的入门教程(附 TODO Demo)
2020/5/26 11:25:23
本文主要是介绍写给跨端玩家:支撑淘宝上亿日活的跨端框架—— Rax 的入门教程(附 TODO Demo),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一些废话
沉寂了两个月,我又回来了。
跟你们猜的一样,我已经到淘系实习了一段时间了,从上一篇文章之后就放了更多的心思在工作上。上篇文章发出去之后,我去腾讯实习了一段时间,等待阿里实习生入职流程开启。
收到淘系的实习生 offer 后,我买了人生中的第一张机票,第一次坐上了飞机,来到了一个陌生的城市——杭州。干净的街道、宽敞的沥青马路,吸引了我这个来自小城市的年轻人。
博客很久没更新了,不管是个人的网站还是掘金,都很少有更新了,偶尔上掘金看看一些好文,总想更新一下,但又没找到好的题材。现在实习了一段时间后,上手了淘系的开源跨端框架——Rax,新奇又好玩,也总结了一些很基础的开发技巧,补充一下官方文档的缺漏(官方文档对于新手来讲确实不太友好)。
基础部分演示项目 Git
仓库:Rax-TODO
进阶技巧演示项目 Git
仓库:Software-Engineering(同时也是我的课程设计,欢迎大伙点个 Star
)
前面的部分是针对只有一点 React
基础的同学的,高端玩家请点击:进阶技巧
项目环境
- node >=10.3.0
- npm >= 6.1.0
前置知识
- JSX
- Hooks
- TypeScript(可选)
- Jest(可选)
- Enzyme(可选)
创建项目
初始化项目
这部分官网文档比较详细了,先看一下官网文档:快速开始
官网文档提供的方案还挺多的,可能会选择困难,我们就从最基础的 TODO 开始,使用 Rax 搭建一个 Web 项目:
npm init rax todo-list 复制代码
选择项目类型
输入上面的命令之后,会使用 npx
安装 rax-cli
脚手架工具,安装完成后会弹出这样的界面:
added 106 packages from 53 contributors in 10.5s ? What's your project type? (Use arrow keys) ❯ App (Build universal application) Component (Build universal component) API (Build universal API library) Plugin (Build plugin for miniapp) 复制代码
使用 上下键
移动箭头,后面的操作同理。
这里我们就直接使用默认的选项,创建一个 APP,按下回车。
选择应用运行平台
? Choose targets your project want to run? (Press <space> to select, <a> to togg le all, <i> to invert selection) ❯◉ Web ◯ Weex ◯ Kraken (Flutter) ◯ Alibaba MiniApp ◯ WeChat MiniProgram 复制代码
使用 空格键
选择,按下 字母a
可以全选,这里我们就先选择 Web,后续如果有编译为 Weex
和 小程序
的需求可以在项目目录的 build.json
中添加。
编译为 Flutter
应用的功能目前还不稳定,且坑比较多,建议动手能力强的玩家尝试,小白就先绕道吧。
选择应用类型
? What's your application type? (Only valid in target: Web/Weex/Kraken) (Use arr ow keys) ❯ Single-page application (SPA) Multi-page application (MPA) Create lite application (The simplest project setup) 复制代码
选择 APP 的类型,是 SPA
还是 MPA
,这里的选项只在 Web/Weex/Kraken(Flutter)
应用中有效。
我们选择默认的选项 SPA
,不明白 SPA
和 MPA
的区别的同学,可以移步文章:认识单页应用(SPA)与多页应用(MPA)
输入作者名字
? What's author's name? (rax): 炽翎 复制代码
选择开发语言
? What type of language do you want to use? (Use arrow keys) ❯ JavaScript TypeScript 复制代码
这里我们就先选择 JavaScript
,后续如果有引入 TypeScript
的需求,可以手动引入。
开启特性
? Do you want to enable these features? (Press <space> to select, <a> to toggle all, <i> to invert selection) ❯◯ Server-side rendering (SSR) (Only valid in target: Web) ◯ Aliyun Function Compute (FaaS) (Only valid in target: Web) ◯ Compatibility with React 复制代码
这里我们就什么都不选。
当然,如果有需要我们可以选择 Compatibility with React
配置与 React 的兼容,也可以为我们的应用开启 服务端渲染(SSR)
。如果有需求开启 Serverless
,也可以选择开启 功能即服务(FaaS)
。SSR
和 FaaS
都只能在 Web
应用中有效。
不懂 SSR
和 Serverless
的同学请自行百度(Google)哈。
自动安装依赖
? Do you want to install dependences automatically after initialization? (Y/n) 复制代码
这里就直接回车,这个选项的意思是询问是否在初始化完成后自动安装依赖。默认是 Yes
,就不用我们手动进入项目文件夹执行 npm install
了。
等待依赖安装完成
To run your app: cd todo-list npm start 复制代码
当终端出现这一段文字的时候,就说明依赖安装完了,我们可以进入到项目的文件夹下,执行 npm start
跑起我们的项目。
启动项目
在执行 npm start
后,终端会显示:
Rax development server has been started: [Web] Development server at: http://localhost:3333/ 复制代码
这时候我们就可以在浏览器输入 Dev Server
的地址,查看我们的项目了。
开始开发
随便选择一款自己喜欢的 IDE,进入项目的文件夹,我们会看到这样的一个目录结构:
. ├── README.md # 项目说明 ├── build.json # 项目构建配置 ├── package.json └── src # 源码目录 ├── app.js # 应用入口文件 ├── app.json # 应用配置,包括路由配置,小程序 window 配置等 ├── public # (可选)静态资源目录,会拷贝内容至 build 目录 ├── components # 应用的公共组件 │ └── Logo # 组件 │ ├── index.css # Logo 组件的样式文件 │ └── index.jsx # Logo 组件 JSX 源码 ├── document # 页面的 HTML 模板 │ └── index.jsx └── pages # 页面 └── Home # home 页面 └── index.jsx 复制代码
开发之前,我们需要了解一些 Rax 下的一些小规矩:
rpx
:默认以750rpx
为屏幕宽度,即1rpx = 1/750 * 屏幕宽度
。样式简写
:在 Rax 中,由于目前兼容性的问题,不支持部分
样式简写,例如:在写border
样式时,应该将各个部分分开:border-width
、border-style
、border-color
。在遇到属性简写在非 Web 平台不生效的问题时,尝试将属性分开或许就能解决问题。
删掉初始页面
我们要做的第一件事是删除初试化后默认的 Home
页面中的 Logo
组件,在 src/components
文件夹下,整个删除。
删除之后,src/pages/Home/index.jsx
肯定会报错,我们先稍作修改,改成 Hello World!
。
// index.jsx import { createElement } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import './index.css'; export default function Home() { return ( <View className="home"> <Text>Hello World!</Text> </View> ); } 复制代码
这个时候会发现页面变成了 Hello World!
,后面应该不用讲解太多,就是使用 React
应用开发的方式,开始愉快的 coding
过程。
可能你会发现,为什么在这里我们只能用 Rax 提供的 View
和 Text
组件?
因为为了使跨端显示效果一致,Rax 为开发者抹平了不同平台之间样式显示不一致的问题。
当然,如果你只是想用 Rax 做一个 Web 应用,那你可以使用 HTML
标签(汗)。
View
组件和 Text
组件的用法可以移步文档:基础组件-View 和 基础组件-Text
创建 Item 组件
按照 耦合度
,我们应该将组件放在 src/pages/Home
文件夹下。
在这个文件夹下,我们创建一个这样的目录:
src/pages/Home └── components # 组件文件夹 └── ListItem # ListItem 组件 ├── index.css # CSS └── index.jsx # JSX 复制代码
首先我们应该构思一下这个 ListItem
应该暴露给父组件哪些接口:
- 每一项对应的
id
- 每一项的内容
- 每一项的完成状态
- 每一项的
onClick
事件
明确了组件应该暴露的接口之后,就可以开始写代码了:
// index.jsx import { createElement } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import './index.css'; const ListItem = (props) => { // 解构 id 完成状态 内容 onClick 事件 const { id, done, content, onClick } = props; // 完成项文字样式 const style = { fontSize: '64rpx', lineHeight: '96rpx', textDecoration: done && 'line-through' }; return ( <View className="list-item" onClick={() => onClick(id)}> <View className="list-dot"></View> <Text style={style}>{content}</Text> </View> ); }; export default ListItem; 复制代码
/* index.css */ .list-item { flex-direction: row; justify-content: flex-start; align-items: center; width: 100%; height: 100rpx; } .list-dot { width: 20rpx; height: 20rpx; margin-right: 20rpx; border-radius: 10rpx; background-color: #333; } 复制代码
创建 List 组件
还是一样,先创建文件:
src/pages/Home └── components # 组件文件夹 ├── List # List 组件 │ ├── index.css # CSS │ └── index.jsx # JSX └── ListItem # ListItem 组件 ├── index.css # CSS └── index.jsx # JSX 复制代码
创建一个 List
组件作为 ListItem
的容器管理所有的 Item
,实现 添加/删除
的功能。
既然要做 添加
功能,那输入框肯定是必不可少的,在我们创建的项目里,默认是没有输入框组件的依赖的,所以我们要先安装 Rax 提供的输入框组件:
npm install rax-textinput --save 复制代码
组件的用法可以转战文档:基础组件-TextInput
// index.jsx import { createElement, useState } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import TextInput from 'rax-textinput'; import ListItem from '../ListItem'; import './index.css'; const List = () => { // 初始化 itemId 每次添加新列表项就 +1 const [itemId, setItemId] = useState(0); // 初始化列表 const [list, setList] = useState([]); // 初始化 TextInput 内容 const [inputValue, setInputValue] = useState(''); // 输入框输入事件 const handleUserInput = (e) => { setInputValue(e.target.value); }; // 添加按钮点击事件 const handleAddButtonClick = () => { // 构造列表项数据结构 const item = { id: itemId, content: inputValue, done: false }; // immutable 思想 生成新的引用 const newList = [...list, item]; setList(newList); // 清空输入框 setInputValue(''); // itemId ++ setItemId(itemId + 1); }; // 列表项点击事件 const handleItemClick = (id) => { // 遍历列表 当事件未完成时标记为已完成 当事件已完成时删除 const newList = list.filter((item) => { if (item.id === id) { if (item.done) { return false; } else { item.done = true; } } return true; }); setList(newList); }; return ( <View className="list"> <View className="list-input-wrapper"> <TextInput className="list-input" value={inputValue} onInput={handleUserInput} /> <View className="list-add-button" onClick={handleAddButtonClick}> <Text>添加</Text> </View> </View> <View className="list-item-wrapper"> {list.map((item) => ( <ListItem key={item.id} id={item.id} content={item.content} done={item.done} onClick={handleItemClick} /> ))} </View> </View> ); }; export default List; 复制代码
.list { align-items: center; } .list-input-wrapper { flex-direction: row; justify-content: flex-start; align-items: center; } .list-add-button { justify-content: center; align-items: center; width: 150rpx; height: 100rpx; margin-left: 20rpx; border-radius: 10px; background-color: #dcdcdc; } .list-input { width: 100%; height: 100rpx; line-height: 96rpx; font-size: 64rpx; border-width: 1px; border-color: #dcdcdc; } .list-item-wrapper { width: 100%; } 复制代码
至此,组件的基本功能就完成了。
引入首页
现在我们要将组件引入首页 Home
中:
import { createElement } from 'rax'; import View from 'rax-view'; import List from './components/List'; import './index.css'; export default function Home() { return ( <View className="home"> <List /> </View> ); } 复制代码
现在就行看到一个能完成基本功能的 TODO 应用了。
进阶技巧
我猜,有些高玩看到我前面写的部分,肯定会说:
啊~ 你这个这么简单,不是有手就行嘛~
有一说一,确实有手就行(误)。
前面的部分只是写给不爱读官方文档或者只有一点 React
基础的同学的,从这个部分开始,会开始引入一些高级的内容。
修改路由配置
在前面创建的项目中,我们会看到项目的文件夹下有一个 app.json
文件,打开它你会看到:
{ "routes": [ { "path": "/", "source": "pages/Home/index" } ], "window": { "title": "Rax App" } } 复制代码
这个文件就是用来控制项目路由,如果后续的开发增加了更多的页面,就需要在 routes
下添加对象。path
就是你新加入的页面的访问路径(URL
),source
就是你新添加的页面所在的文件目录。
修改为多页应用(MPA)
在项目文件夹下还有一个 build.json
文件,里面的内容是这样的:
{ "plugins": [ [ "build-plugin-rax-app", { "targets": ["web"] } ] ] } 复制代码
因为我们之前创建项目的时候,选择的是单页应用(SPA),我们想改成多页应用怎么办? 很简单:
先安装多页应用依赖:
npm install build-plugin-rax-multi-pages --save-dev 复制代码
然后在 targets
所在的对象下,增加一个键 "type"
,值为 "mpa"
,像这样:
{ "plugins": [ [ "build-plugin-rax-app", { "targets": ["web"], "type": "mpa" } ] ] } 复制代码
重启 Dev Server
后会发现页面变成了这样:
添加跨端支持
我们在最开始创建项目的时候,并没有选择多平台,但是 Rax 作为一个跨端开发框架,不添加跨端支持怎么行,这里会给一个教程教大家添加跨端支持(当然一开始就选择好更方便)。
还是 build.json
文件,有一个 targets
数组,想要添加跨端支持,就在数组中添加对应的内容即可:
{ "plugins": [ [ "build-plugin-rax-app", { "targets": ["web", "weex", "miniapp", "wechat-miniprogram"], "type": "mpa" } ] ] } 复制代码
weex
对应 Weex
平台,miniapp
和 wechat-miniprogram
对应 阿里小程序
和 微信小程序
。
查看 Weex 效果
我们在 build.json
中使用了上面的配置后,页面会变成这个样子:
点开 Weex Preview
后,你会发现是一堆 JavaScript
代码,那怎么预览?
有一个稍微麻烦一点的方法,就是先确定你本机在内网的 IP
地址,将 URL
中的 localhost
改成内网 IP
,然后将 URL
转换为二维码(Chrome
有很多插件可以实现)。
在手机上下载 Weex Playground
然后扫描二维码,就能在手机上预览到 APP 的效果。
Weex Playground 下载地址
TypeScript 支持
在前面的项目里,我们没有引入 TypeScript
,那如果想引入应该怎么办?
很简单,在官网的文档中也有讲解:项目开发- TypeScript 支持
只需要先安装 rax-types
和 typescript
:
npm install rax-types typescript --save-dev 复制代码
在项目文件夹下创建 tsconfig.json
文件,使用以下配置:
{ "compilerOptions": { "module": "esNext", "target": "es2015", "outDir": "build", "jsx": "preserve", "jsxFactory": "createElement", "moduleResolution": "node", "sourceMap": true, "alwaysStrict": true, "baseUrl": ".", "paths": { "rax": ["node_modules/rax-types"] } }, "include": ["./src/**/*"] } 复制代码
即可添加 TypeScript
支持。
引入自动化测试
这是一个比较大的坑,以至于让我摸索了一个上午才解决。
Rax 官方文档中并没有自动化测试相关配置的教程,以至于我只能直接在钉钉找负责 Rax 维护的师兄求助,历经千辛万苦终于将测试用例跑通。
首先,我们需要安装几个依赖,数量有点多,建议分开安装:
npm install jest --save-dev npm install @types/jest --save-dev npm install @babel/preset-env --save-dev npm install babel-jest --save-dev npm install rax-test-renderer --save-dev npm install @babel/plugin-proposal-class-properties --save-dev npm install @babel/plugin-proposal-decorators --save-dev npm install @babel/plugin-proposal-export-default-from --save-dev npm install @babel/preset-flow --save-dev npm install @babel/preset-react --save-dev npm install babel-plugin-transform-jsx-stylesheet --save-dev 复制代码
依赖安装好之后,在项目的目录下创建 .babelrc.js
对 Babel
进行配置:
module.exports = function (api) { // Cache the returned value forever and don't call this function again. if (api) api.cache(true); return { presets: [ '@babel/preset-flow', [ '@babel/preset-env', { loose: true } ], [ '@babel/preset-react', { pragma: 'createElement' } ] ], plugins: [ '@babel/plugin-proposal-export-default-from', ['@babel/plugin-proposal-class-properties', { loose: false }], 'babel-plugin-transform-jsx-stylesheet', ['@babel/plugin-proposal-decorators', { legacy: true }] ], ignore: ['build', 'coverage', 'node_modules'] }; }; 复制代码
配置好之后,Jest
还是无法跑通的,要在 package.json
中添加启动脚本:
{ "scripts": { "build": "build-scripts build", "start": "build-scripts start", "lint": "eslint --ext .js --ext .jsx ./", // 添加 jest 启动脚本 "test": "jest" } } 复制代码
同时,还要对 Jest
进行配置:
{ "jest": { "collectCoverage": true, "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js", "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js" } } } 复制代码
配置添加完成之后,在项目的目录下创建一个文件夹:
. └── __mocks__ ├── fileMock.js # 静态资源处理 └── styleMock.js # 样式处理 复制代码
分别在两个文件中加入添加代码:
// fileMock.js module.exports = 'test-file-stub'; 复制代码
// styleMock.js module.exports = {}; 复制代码
配置这个部分的目的是让 Jest
处理样式和静态资源时到 mock 的文件夹下找。因为在测试的时候,测试脚本并不会真的去访问引入的静态资源,遇到需要引用静态资源的地方就引导到 __mocks__
文件夹下查找,就不会因为找不到资源而报错。配置来源于 Jest
官网处理静态文件。
一切配置完成后,就可以在一个需要做测试的组件下创建 __test__
文件夹并将测试脚本放在文件夹下了,或者你也可以直接使用 xxx.test.jsx
为文件命名,这些文件都会被 Jest
识别为测试脚本。
除了 Jest
,Rax 团队还为 Rax 提供了 Enzyme
适配器,示例项目:raxjs/enzyme-adapter-rax,提供了 Enzyme
的使用示例。
总结
得益于淘系强大的技术实力,Rax 的相关生态相对比较完善。同时,性能也非常强大,这里我就不过多介绍了。
Rax 在小程序上的性能甚至优于市面上其他小程序框架:Rax ——完美融合编译时与运行时的双引擎小程序框架。
其他的一些介绍 Rax 的文章可以移步官网的博客。
文章的最后,推荐一下自己的公众号:Hello FE,是我和跟我一起实习的小伙伴们一起运营的,会定期分享一些干货。
同时,关注公众号还有前端书籍大全一份赠送,欢迎大家关注,也欢迎大家进群交流:
这篇关于写给跨端玩家:支撑淘宝上亿日活的跨端框架—— Rax 的入门教程(附 TODO Demo)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南