提交 96445258 编写于 作者: W wanganxp

更新vue、页面、input组件文档

上级 edeb7b7d
# uvue组件概述 # uvue组件概述
## 监听页面生命周期 ## 定义
`4.0` 起可通过组合式 API 实现组件中监听页面生命周期,[示例代码](../vue/component.md#component-lifecycle) - 组件是视图层的基本组成单元。
- 组件是一个单独且可复用的功能模块的封装。
每个组件,包括如下几个部分:以组件名称为标记的开始标签和结束标签、组件内容、组件属性、组件属性值。
- 组件名称由尖括号包裹,称为标签,它有开始标签和结束标签。结束标签的`<`后面用`/`来表示结束。结束标签也称为闭合标签。如下面示例的`<component-name>`是开始标签,`</component-name>`是结束标签。
- 在开始标签和结束标签之间,称为组件内容。如下面示例的`content`
- 开始标签上可以写属性,属性可以有多个,多个属性之间用空格分割
- 每个属性通过`=`赋值
## 组件种类
uvue页面中,支持3种组件:
1. 内置组件,即文档左侧的组件清单
2. 自定义uvue组件,即开发者自己按照vue组件规范编写的uvue文件。这种组件一般由前端工程师编写。如果按照指定目录规范放置,在使用组件时无需import和注册,即[easycom组件规范](../vue/component.md#easycom)
3. uts原生组件。由Android或iOS的原生开发者,按照uts插件的组件规范编写,它在编写时贴近但不完全是vue组件开发规范。不过对于组件的使用者来讲,用法就是标准的uvue组件了。[详见](../plugin/uts-component.md)
## 组件监听页面生命周期
`4.0` 起可通过组合式 API 实现组件中监听页面生命周期,[示例代码](../vue/component.md#component-lifecycle)
## 调用组件方法@methods ## 调用组件方法@methods
......
...@@ -33,11 +33,16 @@ ...@@ -33,11 +33,16 @@
在web端平台,输入框上推逻辑是由浏览器自动完成的,属性`adjust-position`无效。 在web端平台,输入框上推逻辑是由浏览器自动完成的,属性`adjust-position`无效。
但iOS safari软键盘弹出时,整个页面会上推而不是挤压,导致pages.json配置的导航栏会上移到屏幕之外。 但iOS safari软键盘弹出时,整个页面会上推而不是挤压,导致pages.json配置的导航栏会上移到屏幕之外。
## inputmode说明 ## comfirm-type和inputmode说明
inputmode 兼容性:Chrome >= 66、Edge >= 79、Firefox >= 95、Chrome Android >= 66、Firefox for Android >= 79、Safari on iOS >= 12.2、WebView Android >= 66 1. comfirm-type
Web平台弹出键盘使用的是浏览器控制的键盘,在Chrome81+、Safari13.7+之前,键盘右下角文字只能设置完成和搜索,从Chrome81+、Safari13.7+起支持设置发送、下一个。
input组件有 inputmode 和 type、comfirm-tye 3个相似的属性,它们的区别详解如下: 2. inputmode
web平台的inputmode的浏览器兼容性如下: Chrome >= 66、Edge >= 79、Firefox >= 95、Chrome Android >= 66、Firefox for Android >= 79、Safari on iOS >= 12.2、WebView Android >= 66
3. input组件有 inputmode 和 type、comfirm-type 3个相似的属性,它们的区别详解如下:
- type:在 uni-app 和小程序中仅仅是输入框,定义 input 的工作方式,此值决定可输入什么值。比如 number 只能输入数字。 - type:在 uni-app 和小程序中仅仅是输入框,定义 input 的工作方式,此值决定可输入什么值。比如 number 只能输入数字。
- comfirm-type:定义键盘右下角按键的文字 - comfirm-type:定义键盘右下角按键的文字
...@@ -46,5 +51,6 @@ input组件有 inputmode 和 type、comfirm-tye 3个相似的属性,它们的 ...@@ -46,5 +51,6 @@ input组件有 inputmode 和 type、comfirm-tye 3个相似的属性,它们的
同时使用 inputmode 和 comfirm-type 时,若设值冲突,键盘右下角按键类型由 comfirm-type 决定。type 属性和 inputmode 属性并不冲突 同时使用 inputmode 和 comfirm-type 时,若设值冲突,键盘右下角按键类型由 comfirm-type 决定。type 属性和 inputmode 属性并不冲突
## Tips ## Tips
- html规范中input不仅是输入框,还有radio、checkbox、时间、日期、文件选择功能。但在uni-app规范中,input仅仅是输入框,其type属性代表不同的输入框。其他功能有单独的组件或API:[radio组件](radio-group.md)[checkbox组件](checkbox-group.md)[图片选择](../api/choose-image.md)等。
- 从uni-app x 4.0起,App-Android平台 input 点击输入框外的屏幕会自动收起软键盘。 - 从uni-app x 4.0起,App-Android平台 input 点击输入框外的屏幕会自动收起软键盘。
- 从uni-app x 4.0起,App-Android平台 input 的 font-size 默认值统一为 16px。 - 从uni-app x 4.0起,App-Android平台 input 的 font-size 默认值统一为 16px。
# 页面简介 # 页面简介
本文未包括页面生命周期的详细介绍,需另见 [页面](https://uniapp.dcloud.net.cn/tutorial/page.html) ## 页面简介
uni-app x 项目中,页面文件的后缀名`.uvue`文件。
每个uvue文件,都是一个符合`Vue SFC规范`的 vue 文件。
在 uni-app x 中,后缀名是`.uvue`文件
uni-app x 只有 `.uvue`页面,不支持和vue页面并存(因vue是js驱动、webview渲染,uni-app x在app-Android中没有js引擎,app中渲染是原生渲染,无法使用vue页面)。
当然某些组件可以通过条件编译同时适配uni-app和uni-app x,所以在uni-app x的项目中,看到某些组件代码也有vue文件,但这些vue文件并不在uni-app x项目中生效。
另外uts组件插件的入口文件命名是index.vue。因为uts插件在uni-app和uni-app x中均可使用,所以文件后缀名为vue。\
但这个vue文件并不是真正的页面,它只是uts组件插件为了尽可能照顾开发者习惯而参考vue规范定义的原生组件入口文件。
uni-app x 在app-android上,每个页面都是一个全屏activity,不支持透明。
## 页面管理
### 新建页面
新建页面,默认保存在工程根目录下的`pages`目录下。
每次新建页面,均需在`pages.json`中配置`pages`列表;未在`pages.json -> pages` 中注册的页面,在编译阶段会被忽略。pages.json的完整配置参考:[页面配置](./collocation/pagesjson.md)
通过HBuilderX开发 `uni-app` 项目时,在项目上右键“新建页面”,HBuilderX会自动在`pages.json`中完成页面注册,开发更方便。
<!--
同时,HBuilderX 还内置了常用的页面模板,选择这些模板,可以大幅提升开发效率。
<div>
<img src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/pages-add-02.png" style="max-width:450px"></img>
</div>
-->
新建页面时,可以选择`是否创建同名目录`。创建目录的意义在于:
- 如果你的页面较复杂,需要拆分多个附属的uts、css、组件等文件,则使用目录归纳比较合适。
- 如果只有一个页面文件,大可不必多放一层目录。
### 删除页面
删除页面时,需做两件工作:
- 删除`.uvue`文件
- 删除`pages.json -> pages`列表项中的配置 (如使用HBuilderX删除页面,会在状态栏提醒删除pages.json对应内容,点击后会打开pages.json并定位到相关配置项)
### 页面改名
操作和删除页面同理,依次修改文件和 `pages.json`
### pages.json
pages.json是工程的页面管理配置文件,包括:页面路由注册、页面style参数配置(原生标题栏、下拉刷新...)、首页tabbar等众多功能。
其篇幅较长,另见 [pages.json](./collocation/pagesjson.md)
### 设置应用首页@startpage
`pages.json -> pages`配置项中的第一个页面,作为当前工程的首页(启动页)。
```json
{
"pages": [
{
"path": "pages/index/index", //名字叫不叫index无所谓,位置在第一个,就是首页
"style": {
"navigationBarTitleText": "首页" //页面标题
}
},
{
"path": "pages/my",
"style": {
"navigationBarTitleText": "我的"
}
},
]
}
```
## 页面内容构成
uvue页面基于 vue 单文件组件规范。一个页面内,有3个根节点标签:
- 模板区 `<template>`
- 脚本区 `<script>`
- 样式区 `<style>`
```vue
<template>
<view class="content">
<button @click="buttonClick">{{title}}</button>
</view>
</template>
<script setup>
let title = ref("Hello world") //定义一个响应式变量。类似于选项式的定义data
const buttonClick = () => { //方法不再需要写在method下面
console.log("按钮被点了")
}
onReady(() => {
console.log("页面onReady触发") // 页面生命周期,编写页面加载后的逻辑
})
</script>
<style>
.content {
width: 750rpx;
background-color: white;
}
</style>
```
页面内容构成,另有[详细文档](./vue/README.md)
## 页面生命周期 @lifecycle ## 页面生命周期 @lifecycle
...@@ -51,3 +162,6 @@ export default { ...@@ -51,3 +162,6 @@ export default {
## 页面及组件生命周期流程图 @lifecycleflow ## 页面及组件生命周期流程图 @lifecycleflow
![](./static/uni-app-lifecycle-vue3.png)#{.zooming width=1000 margin=auto} ![](./static/uni-app-lifecycle-vue3.png)#{.zooming width=1000 margin=auto}
更多页面生命周期的详细介绍,另见 [uni-app文档](https://uniapp.dcloud.net.cn/tutorial/page.html)
\ No newline at end of file
# uvue概述 # uvue概述
[vue.js](https://vuejs.org/) 是流行的js框架,它提供了简易的模板式写法、数据双向绑定、组件机制。 [vue.js](https://vuejs.org/) 是流行的js框架,它提供了:
1. 简易的模板式写法。降低使用门槛,UI和逻辑分离更清晰。
2. 数据双向绑定。减少手写dom,diff机制提高性能。
3. 组件机制。封装UI和逻辑,让轮子更加丰富。
但 vue.js 并不支持web之外的其他平台,也不支持uts。 但 vue.js 并不支持web之外的其他平台,也不支持uts。
...@@ -14,19 +17,28 @@ uni-app x 中,web平台内置了vue.js,其他平台为 DCloud 参考vue规 ...@@ -14,19 +17,28 @@ uni-app x 中,web平台内置了vue.js,其他平台为 DCloud 参考vue规
在非web平台,uvue 尽可能拉齐了vue.js的功能,但仍有些不常用的功能暂未提供,需注意查看相关文档的兼容性。同时 uvue 也新增了 [easycom](./component.md#easycom) 等技术,简化组件的使用。 在非web平台,uvue 尽可能拉齐了vue.js的功能,但仍有些不常用的功能暂未提供,需注意查看相关文档的兼容性。同时 uvue 也新增了 [easycom](./component.md#easycom) 等技术,简化组件的使用。
截止到HBuilderX 4.14版,uni-app x 兼容的vue版本为3.4。
hello uvue 是非常重要的vue示例,演示了各种vue功能的应用。 hello uvue 是非常重要的vue示例,演示了各种vue功能的应用。
- 插件地址:[https://ext.dcloud.net.cn/plugin?id=15021](https://ext.dcloud.net.cn/plugin?id=15021) - 插件地址:[https://ext.dcloud.net.cn/plugin?id=15021](https://ext.dcloud.net.cn/plugin?id=15021)
- 源码地址:[https://gitcode.net/dcloud/hello-uvue](https://gitcode.net/dcloud/hello-uvue),注意有master和alpha分支,对应HBuilderX最新的正式版和alpha版。 - 源码地址:[https://gitcode.net/dcloud/hello-uvue](https://gitcode.net/dcloud/hello-uvue),注意有master和alpha分支,对应HBuilderX最新的正式版和alpha版。
一个 uvue 页面/组件,有3个根节点标签: # 版本对应@ver
HBuilderX/uni-app x,会跟踪vue版本的升级,版本映射表如下
|HBuilderX |vue版本 |
|-- |-- |
|4.14 |3.4 |
# 页面/组件内容构成@sfc
一个 uvue 页面/组件,符合vue单文件组件规范(SFC),有3个根节点标签:
1. 模板组件区 `<template>` 1. 模板组件区 `<template>`
2. 脚本区 `<script>` 2. 脚本区 `<script>`
3. 样式区 `<style>` 3. 样式区 `<style>`
注意html中,根节点是`<html>``<script>``<style>`是子节点。但在uvue中,这3个节点都是一级节点。
一个简单的选项式页面示例: 一个简单的选项式页面示例:
```vue ```vue
<template> <template>
...@@ -66,7 +78,7 @@ hello uvue 是非常重要的vue示例,演示了各种vue功能的应用。 ...@@ -66,7 +78,7 @@ hello uvue 是非常重要的vue示例,演示了各种vue功能的应用。
template中文名为`模板`,它类似html的标签。但有2个区别: template中文名为`模板`,它类似html的标签。但有2个区别:
1. html中 `script``style` 是 html 的二级节点。但在 uvue 文件中,`template``script``style` 这3个是平级关系。 1. html中 `script``style` 是 html 的二级节点。但在 uvue 文件中,`template``script``style` 这3个是平级关系。
2. html 中写的是 web 标签,但 vue 的 `template` 中写的全都是 vue 组件(包括内置基础组件、自定义uvue组件、uts原生插件组件),每个组件支持属性、事件、vue 指令,还可以绑定 vue 的 data 数据。 2. html 中写的是 web 标签,但 vue 的 `template` 中写的全都是 vue 组件(包括[内置基础组件](../component/README.md)、自定义uvue组件、[uts原生插件组件](../plugin/uts-component.md)),每个组件支持属性、事件、vue 指令,还可以绑定 vue 的 data 数据。
组件,即component,是vue中非常重要的概念,或者说现代开发框架都离不开组件概念。 组件,即component,是vue中非常重要的概念,或者说现代开发框架都离不开组件概念。
...@@ -120,7 +132,7 @@ setup属性声明代表script里的代码为组合式写法,如果没有setup ...@@ -120,7 +132,7 @@ setup属性声明代表script里的代码为组合式写法,如果没有setup
<script setup> <script setup>
let title = ref("Hello world") //定义一个响应式变量。类似于选项式的定义data let title = ref("Hello world") //定义一个响应式变量。类似于选项式的定义data
function buttonClick() { //方法不再需要写在method下面 function buttonClick() { //方法不再需要写在method下面。这里从简使用了function,实际业务中推荐使用箭头函数,有更好的平台一致性
console.log("按钮被点了") console.log("按钮被点了")
} }
onReady(() => { onReady(() => {
......
...@@ -18,29 +18,27 @@ ...@@ -18,29 +18,27 @@
传统vue组件,需要安装、引用、注册,三个步骤后才能使用组件。`easycom` 将其精简为一步。 传统vue组件,需要安装、引用、注册,三个步骤后才能使用组件。`easycom` 将其精简为一步。
只要组件安装在项目的 `components` 目录下或 `uni_modules/插件 id/components` 目录下,并符合 `组件名称/组件名称.(vue|uvue)` 目录结构。就可以不用引用、注册,直接在页面中使用。 只要组件安装在项目的 `components` 目录下或 `uni_modules/插件 id/components/插件 id/插件 id.uvue` 目录下,并符合 `组件名称/组件名称.(vue|uvue)` 目录结构。就可以不用引用、注册,直接在页面中使用。
- 比如 [uni-rate组件](https://ext.dcloud.net.cn/plugin?id=33),它导入到项目后,存放在了目录 /uni_modules/uni-rate/uni-rate.vue - 比如 [uni-loading](https://ext.dcloud.net.cn/plugin?id=15980),它导入到项目后,存放在了目录 /uni_modules/uni-loading/components/uni-loading/uni-loading.uvue
同时它的组件名称也叫 uni-rate,所以这样的组件,不用在 script 里注册和引用。如下: 同时它的组件名称也叫 uni-loading,所以这样的组件,不用在 script 里注册和引用。如下:
```html ```html
<template> <template>
<view> <view>
<uni-rate></uni-rate><!-- 这里会显示一个五角星,并且点击后会自动亮星 --> <uni-loading></uni-loading><!-- 这里会显示一个loading -->
</view> </view>
</template> </template>
<script> <script>
// 这里不用import引入,也不需要在components内注册uni-list组件。template里就可以直接用 // 这里不用import引入,也不需要在components内注册组件。template里就可以直接用
// ... // ...
</script> </script>
``` ```
#### uni_modules 组件 @uni-module-components 这里出现了`uni_module`的概念,简单说下,它是uni-app的一种包管理方案。
> uni_module其实不止服务于组件,它可以服务于组件、js库、页面、项目等所有DCloud插件市场所支持的种类。 `uni_module`其实不止服务于组件,它可以容纳组件、script库、页面、项目等所有DCloud插件市场所支持的种类。
符合uni_module规范的组件都在项目的`uni_modules`目录下,以插件id为目录存放。(项目模板不放在`uni_modules`目录下)
在HBuilderX中点右键可方便的更新插件,插件作者也可以方便的上传插件。 在HBuilderX中点右键可方便的更新插件,插件作者也可以方便的上传插件。
...@@ -55,7 +53,7 @@ uni_module有详细的专项文档,请另行查阅[uni_module规范](https://u ...@@ -55,7 +53,7 @@ uni_module有详细的专项文档,请另行查阅[uni_module规范](https://u
### 手动引入组件 @manual-import-component ### 手动引入组件 @manual-import-component
在新建一个组件后,如果不符合 easycom 规范,则需要手动引入: 不符合 easycom 规范的组件,则需要手动引入:
```vue ```vue
<!-- 组件 child.vue --> <!-- 组件 child.vue -->
......
# 数据绑定模型 # 数据绑定模型
vue的一大特色,就是可以定义一个响应式变量,通过模板绑定的写法,更方便的实现对dom的更改。
在组合式里,定义响应式变量是`ref()`,在选项式里,定义方式是在data里return。
虽然组合式和选项式的定义方式不一样,但在模板里的绑定和使用方式是一样的。
响应式变量被绑定到UI界面后(template和style都可以),
1. 在逻辑script中修改变量,UI界面会自动更新。省却再编写dom代码操作UI。
2. 响应式变量有diff更新机制。比如对于一个大列表的UTSJSONObject数据,其中一项变更时,框架底层会自动计算diff,给UI层差量同步数据。这在大多数情况是很好的,但注意diff这个计算过程本身也会增加耗时。
下面分别讲解各种方式的用法。
## 声明响应式状态 @declaring-reactive-state ## 声明响应式状态 @declaring-reactive-state
### 选项式 API @options-api ### 选项式 API @options-api
选用选项式 API 时,会用 `data` 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 `this`) 上。 选用选项式 API 时,会用 `data` 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 `this`) 上。
data需要特殊类型时,通过 as 来转换。
如下示例中,在data的return中定义了响应式变量:str、num、arr。并在模板中通过`{{ }}`的方式绑定和显示在text组件的内容区中。
示例 [详情](<!-- VUEJSON.E_component-instance.data_data-options.gitUrl -->) 示例 [详情](<!-- VUEJSON.E_component-instance.data_data-options.gitUrl -->)
::: preview <!-- VUEJSON.E_component-instance.data_data-options.webUrl --> ::: preview <!-- VUEJSON.E_component-instance.data_data-options.webUrl -->
<!-- VUEJSON.E_component-instance.data_data-options.code --> <!-- VUEJSON.E_component-instance.data_data-options.code -->
::: :::
data中的响应式变量,如需在script中使用,需通过 `this.xx` 的方式,比如上述的`this.str`
### 组合式 API @composition-api ### 组合式 API @composition-api
选用组合式 API 时,会用 `ref``reactive` 来声明组件的响应式状态。 组合式 API 没有 data 这种选项,而是通过 `ref``reactive` 方法来声明组件的响应式状态。
这种定义方式更加灵活和简洁。但建议把 `ref` 定义都写在开头,否则到处都写也不好找。
#### ref #### ref
在组合式 API 中,推荐使用 `ref()` 函数来声明响应式状态。需要给 `ref` 标注类型,如:`ref<string>()` 使用 `ref()` 函数来定义一个响应式变量。
`ref()` 接收参数,并将其包裹在一个带有 `.value` 属性的 `ref` 对象中返回 需要给 `ref` 标注类型时,通过泛型的写法,如:`ref<string>()`
**注意**:在模板中使用 ref 时,我们不需要附加 `.value`(为了方便起见,当在模板中使用时,ref 会自动解包)。 当然 uts 有一定的自动推导能力,对于特别简单的布尔值/数字/字符串的字面量,不写泛型也可以自动推导类型。
`ref()` 接收参数,并将其包裹在一个带有 `.value` 属性的 `ref` 对象中返回。这个对象,
- 在 uts 中取值时,需要使用 `.value`属性。
- 而在模板中使用 ref 时,不需要附加 `.value`(为了方便起见,在模板中使用时,ref 会自动解包,这样模板里的写法和选项式保持了一致)。
示例 [详情](<!-- VUEJSON.E_reactivity.core_ref_ref.gitUrl -->) 示例 [详情](<!-- VUEJSON.E_reactivity.core_ref_ref.gitUrl -->)
...@@ -32,9 +57,9 @@ ...@@ -32,9 +57,9 @@
#### reactive #### reactive
还有另一种声明响应式状态的方式,即使用 reactive() API。与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性,还可以使用 `readOnly` 来禁止修改 还有另一种声明响应式状态的方式,即使用 reactive() API。与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性,还可以使用 `readOnly` 来禁止修改
值得注意的是,reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的 需要注意:reactive() 返回的是一个原始对象的代理(Proxy),它和原始对象是不相等的。
只有代理对象是响应式的,更改原始对象不会触发更新。因此,使用 Vue 的响应式系统的最佳实践是仅使用你声明对象的代理版本。 只有代理对象是响应式的,更改原始对象不会触发更新。因此,使用 Vue 的响应式系统的最佳实践是仅使用你声明对象的代理版本。
...@@ -50,7 +75,7 @@ ...@@ -50,7 +75,7 @@
可以通过 `defineExpose` 编译器宏来显式指定在 `<script setup>` 组件中要暴露出去的属性: 可以通过 `defineExpose` 编译器宏来显式指定在 `<script setup>` 组件中要暴露出去的属性:
> 在示例中,使用 `defineExpose` 导出一个方法供自动化测试使用 > 在示例中,使用 `defineExpose` 导出一个方法供自动化测试脚本使用
示例 [详情](<!-- VUEJSON.E_component-instance.define-expose_define-expose.gitUrl -->) 示例 [详情](<!-- VUEJSON.E_component-instance.define-expose_define-expose.gitUrl -->)
...@@ -62,11 +87,14 @@ ...@@ -62,11 +87,14 @@
### 在模板里绑定 @bind-template-data ### 在模板里绑定 @bind-template-data
当使用 `Options API` `data``Composition API``ref``reactive` 定义了响应式数据后,可以在模板中使用 `{{}}` 语法绑定数据 当使用 `Options API` `data``Composition API``ref``reactive` 定义了响应式数据后,可以在模板中使用。
- 组件的text区域,使用`{{}}` 语法绑定数据。这常见于`<text>`组件。
- 组件的vue指令中,直接写变量名称。
可以在模板中使用以下任一指令一起 比如下述组件的vue指令
- `v-bind``:`(简写) - `v-bind``:`(简写)。它后面跟着组件的属性名称,可以动态修改组件的属性。
- `v-if``v-else-if``v-else` - `v-if``v-else-if``v-else`
- `v-for` - `v-for`
......
# vue 生态 # vue 生态
## 插件 vue生态的功能,比如vue dev tools、pinia、vuex、i18n,在uni-app x编译到web时均支持,但在App平台目前都不支持。
暂不支持vue插件,比如pinia、vuex、i18n、router。简单的状态管理可以参考文档[全局变量和状态管理](../tutorial/store.md) - vue dev tools for uni-app (x) web教程:[详见](https://uniapp.dcloud.net.cn/tutorial/debug/uni-vue-devtools.html)
- 简单的状态管理可参考文档:[全局变量和状态管理](../tutorial/store.md)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册