- 快速开始
- JSX 介绍
- JSX+ 介绍
- 组件
- 事件处理
- 样式设置
- Hooks 介绍
- Driver 介绍
- 容器差异
- 工程介绍
- 目录结构
- 应用配置
- 应用入口
- 生命周期
- 路由管理
- 简介
- 语法约束
- Hooks
- 多端组件开发
- API 使用
- 静态资源引用
- 项目构建配置
- 页面配置
- 使用原生项目配置文件
- Rax 与小程序代码混用
- FAQ
- 更新日志
- 简介
- 环境变量与 Framework
- Weex Style 支持表
- Weex 组件
- Weex 模块
- 页面降级
- JS Service
- Bundle 解析
- 事件与手势
- 事件通信
- Weex 国际化
- Weex 常见问题
- 简介
- Document
- App Shell
- 代码分离
- 保存至桌面
- 渲染节点快照
- 预加载和预渲染
- 页面保活
- 缓存控制
- PHA 介绍
- 快速开始
- 编码指南
- 数据请求
- FaaS 接入: Now
- FaaS 接入: FC
- 与 Node 应用集成
- 数据请求
- 异步编程
- Rax 错误码
- 简介
- Lite 工程
- 云端一体化工程
- 插件配置
- 插件开发
- 插件简介
- build-plugin-rax-app
- build-plugin-rax-component
- build-plugin-rax-multi-pages
- build-plugin-rax-ssr
- build-plugin-rax-compat-react
- rax-plugin-app 0.1.0 升级
- 调试 Web
- 调试小程序
- 加载性能优化
- 渲染性能优化
- 从 Rax 0.x 升级
- 从 React 迁移
- API 概述
- render
- hydrate
- createPortal
- findDOMNode
- setNativeProps
- getElementById
- unmountComponentAtNode
- createElement
- cloneElement
- createFactory
- isValidElement
- Children
- memo
- Fragment
- createRef
- forwardRef
- useState
- useEffect
- useLayoutEffect
- useContext
- useRef
- useCallback
- useMemo
- useReducer
- useImperativeHandle
- PropTypes
- version
- ActionSheet
- Background
- Keyboard
- Animation
- Transition
- Toast
- Alert
- Confirm
- Loading
- Navigate
- ChooseImage
- Image
- Request
- Network
- File
- Env
- Device
- Clipboard
- AppState
- AsyncStorage
- Accelerometer
- 组件概述
- Text
- View
- TextInput
- Link
- Icon
- Image
- Picture
- Video
- ScrollView
- RecyclerView
- Waterfall
- Embed
- Countdown
- Canvas
- RefreshControl
- Slider
- Modal
- Weex JS Service
- Rax 长列表最佳实践
- 如何减小 Bundle Size
- Rax 0.x 开发工具
- Native 知识扫盲
- iOS 无障碍
- Rax 性能最佳实践
- 从零上手 Rax
- Rax v0.6 组件体验升级
- Rax v0.5 建立服务体系
- Rax v0.3 跨端生态建设
- Rax v0.2 基础能力建设
- 2016 淘宝双促中的 Rax
- Why Rax?
语法约束
由于 Rax 转小程序链路是通过 AST 语法转换的方式将使用 Rax JSX 语法的项目转换到小程序语法的项目,所以受限于实现,我们对开发者使用的语法进行了部分限制(随着转译器的能力增强,限制会越来越少,本篇文档也将持续更新)。
使用限制
静态资源
由于无法识别在 json
文件中配置的静态资源,所以开发者需要指定静态资源的目录,build.json
中的具体配置如下:
{
"plugins": [
[
"rax-plugin-app",
{
"targets": [
"miniapp"
],
"miniapp": {
"constantDir": [
"src/constant"
]
}
}
]
]
}
Context
支持 Context 使用,但不支持以下能力:
- Consumer API,例如以下写法:
<MyContext.Consumer> {value => /* 基于 context 值进行渲染*/} </MyContext.Consumer>
- 向上追溯最近的 Provider。当组件订阅了 Context 对象时,其会从最先渲染的 Provider 中读取到 Provider 的 value 而不是向上往父组件找离自己最近的 Provider。
- class.contextType,例如以下写法:
定义 contextType 请使用以下写法:class MyClass extends Rax.Component { } MyClass.contextType = MyContext;
class MyClass extends Rax.Component { static contextType = MyContext }
JSX 语法
基础语法
引号
由于小程序中变量绑定需要通过 "{{}}"
,双引号来包裹,所以在 JSX 中尽量不要使用双引号,以至于产生冲突。
组件导出方式
为了方便编译器找到导出的组件,我们对导出组件做了如下限制:
- 默认导出的必须是组件,即
export default MyComponent;
- 当导出的组件需要被某个函数处理的时候,函数的第一个参数必须是组件,即
export default handleComponent(MyComponent);
扩展运算符
支持给组件属性的值中使用扩展运算符:
<View xxx = {...object}></View>
不支持直接在组件上使用扩展运算符:
<View {...props}></View>
模板字符串
JSX 上暂时不能使用模板字符串
Render Props
组件的 props
无法传递 JSX 模板,如以下用法:
<CustomComponent renderItem={<View>item</View>} />
Ref
目前支持通过 useRef
和字符串的方式创建 Ref
。
支付宝小程序需要开启 component2。
组件文件
一个组件文件只支持导出一个组件,例如不支持以下用法:
export function Title() {
return <View>Title</View>;
}
export function Content() {
return <View>Content</View>;
}
组件渲染
一般情况下,目前一个组件文件中只支持定义并使用一个组件,例如不支持以下用法:
function Title() {
return <View>Title</View>;
}
export default function Home() {
return <Title />;
}
但是为了满足部分这方面的需求,转译器支持在 Class Component
中如下用法:
export default class Home extends Component {
renderTitle(title) {
return <View>{title}</View>;
}
render() {
return (
<View>{this.renderTitle('Title')}</View>
)
}
}
条件渲染
由于条件渲染存在较大的灵活性,所以目前支持以下条件渲染的方式:
通过变量赋值的形式:
export default class Home extends Component {
state = {
status: false
};
render() {
const { status } = this.state;
let result;
if (status) {
result = <View>status 1</View>
} else {
result = <View>status 2</View>
}
return (
<View>
{result}
</View>
);
}
}
并且支持使用 else if
,但是需要注意的是,在写 if
表达式的时候,需要在后面标准的加上 {}
,代表代码块。
通过三元表达式:
export default class Home extends Component {
state = {
status: false,
};
render() {
const { status } = this.state;
return (
<View>{status <View>status 1</View> : <View>status 2</View>}</View>
);
}
}
并且支持使用多层三元表达式。
通过 JSX+ 语法中的 x-if
:
export default class Home extends Component {
state = {
status: false,
};
render() {
const { status } = this.state;
return (
<View>
<View x-if={status}>
<View>status 1</View>
</View>
<View x-else>status 2</View>
</View>
);
}
}
通过逻辑表达式:
export default class Home extends Component {
state = {
status: false,
};
render() {
const { status } = this.state;
return (
<View>{status && <View>status 1</View>}</View>
);
}
}
循环渲染
循环渲染最大的限制在于你必须保证你循环遍历的变量的类型是数组。
其它限制循环渲染写法的原因产生于两个方面:
- 循环自定义组件时,需要去派发传递给自定义组件的属性(即
props
)
- 循环渲染中会产生新的作用域与作用域中的变量
基于以上原因循环渲染只支持以下用法:
使用 JSX 中常用到的 map
,简单用法例如:
export default class Home extends Component {
state = {
list: [],
};
render() {
const { list } = this.state;
return (
<View>
{list.map((item, index) => {
return <View>{item.title}</View>;
})}
</View>
);
}
}
但是,在某些复杂场景下,一些用法就不支持了:
需要在 JSX 中的复杂表达式里使用到循环产生的临时变量,如以下写法是不支持的:
export default class Home extends Component {
state = {
list: [],
};
render() {
const { list } = this.state;
return (
<View>
{list.map((item, index) => {
return (
<View
style={{
marginRight: index < 2 18 : 0,
}}
></View>
);
})}
</View>
);
}
}
如果有这样的需求,建议使用以下写法来避免转移失败,在 map 函数体内将复杂表达式赋值给一个变量,然后在 jsx 中直接使用变量的形式:
export default class Home extends Component {
state = {
list: [],
};
render() {
const { list } = this.state;
return (
<View>
{list.map((item, index) => {
const marginRight = index < 2 18 : 0;
return (
<View
style={{
marginRight,
}}
></View>
);
})}
</View>
);
}
}
多层循环的 JSX 中使用到临时变量,如以下用法是不支持的:
export default class Home extends Component {
state = {
list: [['a'], ['b']],
};
render() {
const { list } = this.state;
return (
<View>
{list.map(item => {
return item.map(item2 => {
return <View>{item2}</View>;
});
})}
</View>
);
}
}
使用 JSX+ 中的 x-for
:
在这种用法中,开发者得到的便利不只是可以少写一些代码,更重要的是,这种用法是支持多层循环渲染的,比如,你可以这样写:
export default class Home extends Component {
state = {
list: [['a'], ['b']],
};
render() {
const { list } = this.state;
return (
<View>
<View x-for={item in list}>
<View x-for={item2 in item}>{item2}</View>
</View>
</View>
);
}
}
事件绑定
事件名
所有的事件名必须是 on
开头。
在循环中使用
在循环中绑定事件的时候尽量在 JSX 中直接使用循环中产生的临时变量,例如:
正确做法:
<View>
{
list.map(item => {
const url = item.url;
return <View onClick={() => handleClick(url)}></View>
});
}
</View>
错误做法:
<View>
{
list.map(item => {
const url = item.url;
const handleClick = () => {
console.log(url);
}
return <View onClick={handleClick}></View>
});
}
</View>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论