From 587a8e205b9efc1d984b07ff43701e23f4756ff3 Mon Sep 17 00:00:00 2001 From: anne-lxm <1076217653@qq.com> Date: Thu, 16 Sep 2021 16:00:57 +0800 Subject: [PATCH] =?UTF-8?q?docs:vue3=E6=96=87=E6=A1=A3=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=B7=B2=E7=BF=BB=E8=AF=91=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/vue-vuex.md | 146 ---- docs/vue3-api.md | 377 +-------- docs/vue3-basics.md | 1702 +++------------------------------------ docs/vue3-components.md | 1491 +--------------------------------- docs/vue3-vuex.md | 1035 ++---------------------- 5 files changed, 253 insertions(+), 4498 deletions(-) diff --git a/docs/vue-vuex.md b/docs/vue-vuex.md index 37e3a4ac4..cf383b1b1 100644 --- a/docs/vue-vuex.md +++ b/docs/vue-vuex.md @@ -181,28 +181,6 @@ app.$mount() -```html - - - -``` @@ -218,37 +196,6 @@ app.$mount() 在 `uni-app` 项目根目录下,`store` 目录 `index.js` 文件下: -```js - -import Vue from 'vue' -import Vuex from 'vuex' - -Vue.use(Vuex); - -const store = new Vuex.Store({ - state: { - todos: [{ - id: 1, - text: '我是内容一', - done: true - }, - { - id: 2, - text: '我是内容二', - done: false - } - ] - }, - getters: { - doneTodos: state => { - return state.todos.filter(todo => todo.done) - } - } -}) - -export default store - -``` @@ -335,51 +282,6 @@ export default store - 在 `mutation` 传参(载荷)可以传递一个参数。 -```js - -import Vue from 'vue' -import Vuex from 'vuex' - -Vue.use(Vuex); - -const store = new Vuex.Store({ - state: { - count: 1 - }, - mutations: { - add(state, n) { - state.count += n - } - } -}) -export default store -``` - - -```html - - - -``` - 在 `mutation` 传参(载荷)可以也可以传递一个对象。让我们修改上面累加器的例子: @@ -476,43 +378,12 @@ export default store ``` -```js - -import Vue from 'vue' -import Vuex from 'vuex' - -Vue.use(Vuex); - -const store = new Vuex.Store({ - state: { - count: 1 - }, - mutations: { - add(state) { - // 变更状态 - state.count += 2 - } - } -}) -export default store -``` - - 我们要通过提交 `mutation` 的方式来改变状态数据,是因为我们想要更明确地追踪到状态的变化。如果是类似下面这样异步的话: -```js - mutations: { - someMutation (state) { - api.callAsyncMethod(() => { - state.count++ - }) - } - } -``` 我们就不知道什么时候状态会发生改变,所以也就无法追踪了,这与 `mutation` 的设计初心相悖,所以强制规定它必须是同步函数。 @@ -570,26 +441,9 @@ export default store - `mapActions` 也支持传入参数(载荷): -```js - methods: { - ...mapActions([ - 'addCountAction' - // 将 `this.addCountAction(amount)` 映射为 - //`this.$store.dispatch('addCountAction', amount)` - ]), - } -``` - `mapActions` 也支持传递一个对象: -```js - methods: { - ...mapActions({ - addCount: 'addCountAction', - // 将 `this.addCount()` 映射为 `this.$store.dispatch('addCountAction')` - }) - } -``` diff --git a/docs/vue3-api.md b/docs/vue3-api.md index 27d29327b..731abc465 100644 --- a/docs/vue3-api.md +++ b/docs/vue3-api.md @@ -1,288 +1,28 @@ -## 应用配置 -`config` 是一个包含了 `Vue` 应用全局配置的对象。你可以在应用挂载前修改其以下 `property`: -```js -const app = Vue.createApp({}) -app.config = {...} -``` -|应用配置|描述 |H5 |App端|说明 | -|-- |-- |-- |-- |-- | -|errorHandler |指定一个处理函数,来处理组件渲染方法执行期间以及侦听器抛出的未捕获错误。[详情](https://vue3js.cn/docs/zh/api/application-config.html#errorhandler) |√ |√ || -|warnHandler |为 `Vue` 的运行时警告指定一个自定义处理函数。[详情](https://vue3js.cn/docs/zh/api/application-config.html#warnhandler) |√ |√ || -|globalProperties |添加可以在应用程序内的任何组件实例中访问的全局 `property`。[详情](https://vue3js.cn/docs/zh/api/application-config.html#globalproperties) |√ |√ || -|isCustomElement |指定一个方法,用来识别在 `Vue` 之外定义的自定义元素。[详情](https://vue3js.cn/docs/zh/api/application-config.html#iscustomelement) |√ |√ || -|optionMergeStrategies |为自定义选项定义合并策略。[详情](https://vue3js.cn/docs/zh/api/application-config.html#optionmergestrategies) |√ |√ || -|performance|设置为 `true` 以在浏览器开发工具的 `performance/timeline` 面板中启用对组件初始化、编译、渲染和更新的性能追踪。[详情](https://vue3js.cn/docs/zh/api/application-config.html#performance) |√ |x |只在Web环境下支持| -## 应用 API -在 Vue 3 中,改变全局 `Vue` 行为的 `API` 现在被移动到了由新的 `createApp` 方法所创建的应用实例上。此外,现在它们的影响仅限于该特定应用实例: - -```js -import { createApp } from 'vue' - -const app = createApp({}) -``` - - -调用 `createApp` 返回一个应用实例。该实例提供了一个应用上下文。应用实例挂载的整个组件树共享相同的上下文,该上下文提供了之前在 `Vue 2.x` 中“全局”的配置。 - -另外,由于 `createApp` 方法返回应用实例本身,因此可以在其后链式调用其它方法,这些方法可以在以下部分中找到。 - - -|应用 API|描述 |H5 |App端| -|-- |-- |-- |-- | -|component |注册或检索全局组件。[详情](https://vue3js.cn/docs/zh/api/application-api.html#component) |√ |√ | -|config |包含应用配置的对象。[详情](https://vue3js.cn/docs/zh/api/application-api.html#config) |√ |√ | -|directive |注册或检索全局指令。[详情](https://vue3js.cn/docs/zh/api/application-api.html#directive) |√ |√ | -|mixin |在整个应用范围内应用混入。[详情](https://vue3js.cn/docs/zh/api/application-api.html#mixin) |√ |√ | -|provide|设置一个可以被注入到应用范围内所有组件中的值。[详情](https://vue3js.cn/docs/zh/api/application-api.html#provide) |√ |√ | -|use|安装 `Vue.js` 插件。[详情](https://vue3js.cn/docs/zh/api/application-api.html#use) |√ |√ | - - - -## 全局 API - -|全局 API|描述 |H5 |App端| -|-- |-- |-- |-- | -|createApp |返回一个提供应用上下文的应用实例。应用实例挂载的整个组件树共享同一个上下文。[详情](https://vue3js.cn/docs/zh/api/global-api.html#createapp) |√ |√ | -|h |返回一个”虚拟节点“,通常缩写为 `VNode`:一个普通对象,其中包含向 `Vue` 描述它应在页面上渲染哪种节点的信息,包括所有子节点的描述。[详情](https://vue3js.cn/docs/zh/api/global-api.html#h) |√ |x | -|defineComponent |从实现上看,`defineComponent` 只返回传递给它的对象。但是,就类型而言,返回的值有一个合成类型的构造函数,用于手动渲染函数、`TSX` 和 `IDE` 工具支持。[详情](https://vue3js.cn/docs/zh/api/global-api.html#definecomponent) |√ |x | -|defineAsyncComponent |创建一个只有在需要时才会加载的异步组件。[详情](https://vue3js.cn/docs/zh/api/global-api.html#defineasynccomponent) |√ |x | -|resolveComponent |如果在当前应用实例中可用,则允许按名称解析 `component`。返回一个 `Component`。[详情](https://vue3js.cn/docs/zh/api/global-api.html#resolvecomponent) |√ |x | -|resolveDynamicComponent|允许使用与 `component :is=""` 相同的机制来解析一个 `component`。[详情](https://vue3js.cn/docs/zh/api/global-api.html#resolvedynamiccomponent) |√ |x | -|resolveDirective|如果在当前应用实例中可用,则允许通过其名称解析一个 `directive`。返回一个 `Directive`。[详情](https://vue3js.cn/docs/zh/api/global-api.html#resolvedirective) |√ |x | -|withDirectives|允许将指令应用于 `VNode`。返回一个包含应用指令的 `VNode`。[详情](https://vue3js.cn/docs/zh/api/global-api.html#withdirectives) |√ |x | -|createRenderer|createRenderer 函数接受两个泛型参数: `HostNode` 和 `HostElement`,对应于宿主环境中的 `Node` 和 `Element` 类型。[详情](https://vue3js.cn/docs/zh/api/global-api.html#createrenderer) |√ |x| -|nextTick|将回调推迟到下一个 `DOM` 更新周期之后执行。在更改了一些数据以等待 `DOM` 更新后立即使用它。[详情](https://vue3js.cn/docs/zh/api/global-api.html#nexttick) |√ | x | - - - - -## 选项/Data - - -|Data|描述 |H5 |App端| -|-- |-- |-- |-- | -|data |返回组件实例的 `data` 对象的函数。[详情](https://vue3js.cn/docs/zh/api/options-data.html) |√ |√ | -|props |`props` 可以是数组或对象,用于接收来自父组件的数据。[详情](https://vue3js.cn/docs/zh/api/options-data.html#props) |√ |√ | -|computed |计算属性将被混入到组件实例中。所有 `getter` 和 `setter` 的 `this` 上下文自动地绑定为组件实例。[详情](https://vue3js.cn/docs/zh/api/options-data.html#computed) |√ |√ | -|methods |methods 将被混入到组件实例中。可以直接通过 `VM` 实例访问这些方法,或者在指令表达式中使用。方法中的 `this` 自动绑定为组件实例。[详情](https://vue3js.cn/docs/zh/api/options-data.html#methods) |√ |√ | -|watch |一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。[详情](https://vue3js.cn/docs/zh/api/options-data.html#watch) |√ |√ | -|emits|emits 可以是数组或对象,从组件触发自定义事件,`emits` 可以是简单的数组,或者对象作为替代,允许配置和事件验证。[详情](https://vue3js.cn/docs/zh/api/options-data.html#emits) |√ |√ | - - -## 选项/DOM - - -|DOM|描述 |H5 |App端|说明 | -|-- |-- |-- |-- |-- | -|template |一个字符串模板作为 `component` 实例的标识使用。[详情](https://vue3js.cn/docs/zh/api/options-dom.html#template) |√ |x | uni-app使用的vue是只包含运行时的版本 | -|render |字符串模板的另一种选择,允许你充分利用 `JavaScript` 的编程功能。[详情](https://vue3js.cn/docs/zh/api/options-dom.html#render) |√ | x | - | - - - -## 选项/生命周期钩子 - - -|生命周期钩子|描述 |H5 |App端| -|-- |-- |-- |-- | -|beforeCreate |在实例初始化之后,数据观测` (data observer) `和 `event/watcher` 事件配置之前被调用。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#beforecreate) |√ |√ | -|created |在实例创建完成后被立即调用。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#created) |√ |√ | -|beforeMount |在挂载开始之前被调用:相关的 `render` 函数首次被调用。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#beforemount) |√ |√ | -|mounted |实例被挂载后调用,这时 `Vue.createApp({}).mount()` 被新创建的 `vm.$el` 替换了。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#mounted) |√ |√ | -|beforeUpdate |数据更新时调用,发生在虚拟 `DOM` 打补丁之前。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#beforeupdate) |√ |√ | -|updated|由于数据更改导致的虚拟 `DOM` 重新渲染和打补丁,在这之后会调用该钩子。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#updated) |√ |√ | -|activated|被 `keep-alive` 缓存的组件激活时调用。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#activated) |√ |√ | -|deactivated|被 `keep-alive` 缓存的组件停用时调用。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#deactivated) |√ |√ | -|beforeUnmount|在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#beforeunmount) |√ |√ | -|unmounted|卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#unmounted) |√ |√ | -|errorCaptured |当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#errorcaptured) |√ |√ | -|renderTracked |跟踪虚拟 `DOM` 重新渲染时调用。钩子接收 `debugger event` 作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#rendertracked) |√ |√ | -|renderTriggered |当虚拟 `DOM` 重新渲染为 `triggered.Similarly` 为`renderTracked`,接收 `debugger event` 作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。[详情](https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#rendertriggered) |√ |√ | - - -## 选项/资源 - - -|资源|描述 |H5 |App端| -|-- |-- |-- |-- | -|directives |包含组件实例可用指令的哈希表。[详情](https://vue3js.cn/docs/zh/api/options-assets.html#directives) |√ |√ | -|components |包含组件实例可用组件的哈希表。[详情](https://vue3js.cn/docs/zh/api/options-assets.html#components) |√ |√ | - - -## 选项/组合 - - -|组合|描述 |H5 |App端| -|-- |-- |-- |-- | -|mixins |接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用特定的选项合并逻辑。[详情](https://vue3js.cn/docs/zh/api/options-composition.html#mixins) |√ |√ | -|extends |允许声明扩展另一个组件 (可以是一个简单的选项对象或构造函数)。这主要是为了便于扩展单文件组件。[详情](https://vue3js.cn/docs/zh/api/options-composition.html#extends) |√ |√ | -|provide / inject |这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。[详情](https://vue3js.cn/docs/zh/api/options-composition.html#provide-inject) |√ |√ | -|setup |`setup` 函数是一个新的组件选项。它作为在组件内部使用组合式 `API` 的入口点。[详情](https://vue3js.cn/docs/zh/api/options-composition.html#setup) |√ |√ | - - - -## 选项/杂项 - - -|杂项|描述 |H5 |App端| -|-- |-- |-- |-- | -|name |允许组件模板递归地调用自身。注意,组件在全局用 `Vue.createApp({}).component({})` 注册时,全局 `ID` 自动作为组件的 `name`。[详情](https://vue3js.cn/docs/zh/api/options-misc.html#name) |√ |√ | -|delimiters |设置用于模板内文本插入的分隔符。[详情](https://vue3js.cn/docs/zh/api/options-misc.html#delimiters) |√ |x | -|inheritAttrs |默认情况下父作用域的不被认作 `props` 的 `attribute` 绑定 (`attribute bindings`) 将会“回退”且作为普通的 `HTML attribute` 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,通过设置 `inheritAttrs` 到 `false`,这些默认行为将会被去掉。[详情](https://vue3js.cn/docs/zh/api/options-misc.html#inheritattrs) |√ |√ | - - - -## 实例 property - - -|实例 property|描述 |H5 |App端|说明 | -|-- |-- |-- |-- |-- | -|$data |组件实例观察的数据对象。组件实例代理了对其 `data` 对象 `property` 的访问。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#data) |√ |√ || -|$props |当前组件接收到的 `props` 对象。组件实例代理了对其 `props` 对象 `property` 的访问。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#props) |√ |√ || -|$el |组件实例使用的根 `DOM` 元素。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#el) |√ | x|| -|$options |用于当前组件实例的初始化选项。需要在选项中包含自定义 `property` 时会有用处。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#options) |√ |√ || -|$parent |父实例,如果当前实例有的话。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#parent) |√ |√ | H5端 `view`、`text` 等内置标签是以 `Vue` 组件方式实现,`$parent` 会获取这些到内置组件,导致的问题是 `this.$parent` 与其他平台不一致,解决方式是使用 `this.$parent.$parent` 获取或自定义组件根节点由 `view` 改为 `div`| -|$root |当前组件树的根组件实例。如果当前实例没有父实例,此实例将会是其自己。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#root) |√ |√ || -|$slots |用来访问被插槽分发的内容。每个具名插槽有其相应的 `property` (例如:`v-slot:foo` 中的内容将会在 `this.$slots.foo` 中被找到)。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#slots) |√ |x || -|$refs |一个对象,持有注册过 `ref attribute` 的所有 `DOM` 元素和组件实例。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#refs) |√ |√ | 非H5端只能用于获取自定义组件,不能用于获取内置组件实例(如:`view`、`text`)| -|$attrs |包含了父作用域中不作为组件 `props` 或自定义事件。[详情](https://vue3js.cn/docs/zh/api/instance-properties.html#attrs) |√ |√ |-| - - -## 实例方法 - -|实例方法|描述 |H5 |App端| -|-- |-- |-- |-- | -|$watch |侦听组件实例上的响应式 `property` 或函数计算结果的变化。[详情](https://vue3js.cn/docs/zh/api/instance-methods.html#watch) |√ |√ | -|$emit |触发当前实例上的事件。附加参数都会传给监听器回调。[详情](https://vue3js.cn/docs/zh/api/instance-methods.html#emit) |√ |√ | -|$forceUpdate |迫使组件实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。[详情](https://vue3js.cn/docs/zh/api/instance-methods.html#forceupdate) |√ |√ | -|$nextTick |将回调延迟到下次 `DOM` 更新循环之后执行。在修改数据之后立即使用它,然后等待 `DOM` 更新。[详情](https://vue3js.cn/docs/zh/api/instance-methods.html#nexttick) |√ |√ | - - - - -## 指令 - -|Vue 指令 |描述 |H5 |App端|说明 | -| -- | -- | -- |-- | -- | -|v-text | 更新元素的 `textContent`。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-text) |√ |√ | | -|v-html | 更新元素的 `innerHTML`。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-html) |√ | √ | x | | -|v-show | 根据表达式的真假值,切换元素的 `display CSS property`。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-show) |√ | √ | | -|v-if | 根据表达式的真假值来有条件地渲染元素。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-if) |√ | √ | | -|v-else | 为 `v-if` 或者 `v-else-if` 添加`“else 块”`。[详情](https://vue3js.cn/docs/zh/api/directives.html#v-else) |√ | √ | | -|v-else-if| 表示 `v-if` 的`“else if 块”`。可以链式调用。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-else-if) |√ | √ | | -|v-for | 基于源数据多次渲染元素或模板块。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-for) |√ | √ | | -|v-on | 绑定事件监听器。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-on) |√ | √ | | -|v-bind | 动态地绑定一个或多个 `attribute`,或一个组件 `prop` 到表达式。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-bind) |√ | √ || -|v-model| 在表单控件或者组件上创建双向绑定。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-model) |√ | √ | | -|v-slot | 提供具名插槽或需要接收 `prop` 的插槽。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-slot) |√ | √ | | -|v-pre | 跳过这个元素和它的子元素的编译过程。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-pre) |√ | √ | | -|v-cloak| 这个指令保持在元素上直到关联组件实例结束编译。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-cloak) |√ | x | | -|v-once | 只渲染元素和组件一次。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-once) |√ | √ | | |v-is | 在 `DOM` 内模板使用时,模板受原生 `HTML` 解析规则的约束。 [详情](https://vue3js.cn/docs/zh/api/directives.html#v-is) |√ | x | - | -## 特殊属性 - -|特殊属性 |描述 |H5 |App端|说明 | -| -- | -- | -- |-- | -- | -|key | `key` 的特殊 `attribute` 主要用在 `Vue` 的虚拟 `DOM` 算法,在新旧 `nodes` 对比时辨识 `VNodes`。 [详情](https://vue3js.cn/docs/zh/api/special-attributes.html#key) |√ | √ | | -|ref | ref 被用来给元素或子组件注册引用信息。 [详情](https://vue3js.cn/docs/zh/api/special-attributes.html#ref) |√ | √ | 非 H5 平台只能获取 `vue` 组件实例不能获取到内置组件实例| -|is | 使用[动态组件](https://vue3js.cn/docs/zh/guide/component-dynamic-async.html)。 [详情](https://vue3js.cn/docs/zh/api/special-attributes.html#is) |√ | √ | - | - - - -## 内置组件 - -|内置组件 |描述 |H5 |App端| -| -- | -- | -- |-- | -|component | 渲染一个“元组件”为动态组件。依 `is` 的值,来决定哪个组件被渲染。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#component) |√ | √ | | -|transition | 作为单个元素/组件的过渡效果。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#transition) |√ | x | | -|transition-group | 作为多个元素/组件的过渡效果。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#transition-group) |√ | x | | -|keep-alive | 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,主要用于保留组件状态或避免重新渲染。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#keep-alive) |√ |x | | -|slot | 作为组件模板之中的内容分发插槽。`slot` 元素自身将被替换。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#slot) |√ | √ | | -|teleport | 将模板的一部分移动到 `DOM` 中 `Vue app` 之外的其他位置。 [详情](https://vue3js.cn/docs/zh/api/built-in-components.html#teleport) |√ | x | - | - - -## 响应性 API -### 响应性基础 API -|响应性基础 API|描述 |H5 |App端| -|-- |-- |-- |-- | -|reactive |返回对象的响应式副本。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#reactive) |√ |√ | -|readonly |获取一个对象 (响应式或纯对象) 或 `ref` 并返回原始代理的只读代理。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#readonly) |√ |√ | -|isProxy |检查对象是 `reactive` 还是 `readonly`创建的代理。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#isproxy) |√ |√ | -|isReactive |检查对象是否是 `reactive`创建的响应式 `proxy`。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#isreactive) |√ |√ | -|isReadonly |检查对象是否是由`readonly`创建的只读代理。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#isreadonly) |√ |√ | -|toRaw |返回 `reactive` 或 `readonly` 代理的原始对象。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#toraw) |√ |√ | -|markRaw |标记一个对象,使其永远不会转换为代理。返回对象本身。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#markraw) |√ |√ | -|shallowReactive |创建一个响应式代理,该代理跟踪其自身 `property` 的响应性,但不执行嵌套对象的深度响应式转换 (暴露原始值)。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#shallowreactive) |√ |√ | -|shallowReadonly |创建一个代理,使其自身的 `property` 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。[详情](https://vue3js.cn/docs/zh/api/basic-reactivity.html#shallowreadonly) |√ |√ | -### Refs -|Refs|描述 |H5 |App端| -|-- |-- |-- |-- | -|ref |接受一个内部值并返回一个响应式且可变的 `ref` 对象。`ref` 对象具有指向内部值的单个 property `.value`。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#ref) |√ |√ | -|unref |如果参数为 `ref`,则返回内部值,否则返回参数本身。这是 `val = isRef(val) ? val.value : val`。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#unref) |√ |√ | -|toRef |可以用来为源响应式对象上的 `property` 性创建一个 `ref`。然后可以将 `ref` 传递出去,从而保持对其源 `property` 的响应式连接。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#toref) |√ |√ | -|toRefs |将响应式对象转换为普通对象,其中结果对象的每个 `property` 都是指向原始对象相应 `property` 的`ref`。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#torefs) |√ |√ | -|isRef |检查值是否为`ref`对象[详情](https://vue3js.cn/docs/zh/api/refs-api.html#isref) |√ |√ | -|customRef |创建一个自定义的 `ref`,并对其依赖项跟踪和更新触发进行显式控制。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#customref) |√ |√ | -|shallowRef |创建一个 `ref`,它跟踪自己的 `.value` 更改,但不会使其值成为响应式的。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#shallowref) |√ |√ | -|triggerRef |手动执行与 `shallowRef` 关联的任何效果。[详情](https://vue3js.cn/docs/zh/api/refs-api.html#triggerref) |√ |√ | - - - -### Computed 与 watch - -|Computed 与 watch|描述 |H5 |App端| -|-- |-- |-- |-- | -|computed |使用 `getter` 函数,并为从 `getter` 返回的值返回一个不变的响应式 `ref` 对象。[详情](https://vue3js.cn/docs/zh/api/computed-watch-api.html#computed) |√ |√ | -|watchEffect |在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它。[详情](https://vue3js.cn/docs/zh/api/computed-watch-api.html#watcheffect) |√ |√ | -|watch |`watch` API 与选项式 API `this.$watch` (以及相应的 `watch` 选项) 完全等效。`watch` 需要侦听特定的 `data` 源,并在单独的回调函数中副作用。[详情](https://vue3js.cn/docs/zh/api/computed-watch-api.html#watch) |√ |√ | - - - - -## 组合式 API - -|组合式 API|描述 |H5 |App端| -|-- |-- |-- |-- | -|setup |一个组件选项,在创建组件之前执行,一旦 `props` 被解析,并作为组合式 `API` 的入口点。[详情](https://vue3js.cn/docs/zh/api/composition-api.html#setup) |√ |√ | -|生命周期钩子 |可以使用直接导入的 `onX` 函数注册生命周期钩子。[详情](https://vue3js.cn/docs/zh/api/composition-api.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90) |√ |√ | -|Provide / Inject |provide 和 inject 启用依赖注入。只有在使用当前活动实例的 `setup()` 期间才能调用这两者。[详情](https://vue3js.cn/docs/zh/api/composition-api.html#provide-inject) |√ |√ | -|getCurrentInstance |允许访问对高级使用或库创建者有用的内部组件实例。[详情](https://vue3js.cn/docs/zh/api/composition-api.html#getcurrentinstance) |√ |√ | - - - - -## 全局变量 - -实现全局变量的方式需要遵循 `Vue` 单文件模式的开发规范。详细参考:[uni-app全局变量的几种实现方式](https://ask.dcloud.net.cn/article/35021)。 - -## 常见问题 - -### 1. 如何获取上个页面传递的数据 - -在 `onLoad` 里得到,`onLoad` 的参数是其他页面打开当前页面所传递的数据。 ### 2. 如何设置全局的数据和全局的方法 @@ -290,120 +30,7 @@ const app = createApp({}) `uni-app` 内置了 [Vuex](https://uniapp.dcloud.io/vue-vuex) ,在`app`里的使用,可参考 `hello-uniapp` ` store/index.js`。 -```javaScript - //store.js - import {createStore} from 'vuex' - const store = createStore({ - state: {...}, - mutations: {...}, - actions: {...} - }) - export default store - - //main.js - import App from './App' - import {createSSRApp} from 'vue' - import store from './store' - export function createApp() { - const app = createSSRApp(App) - app.use(store) - return { - app - } - } - - //test.vue 使用时: - import {mapState,mapMutations} from 'vuex' -``` - - - -### 3. 如何捕获 app 的 onError - -由于 `onError` 并不是完整意义的生命周期,所以只提供一个捕获错误的方法,在 `app` 的根组件上添加名为 `onError` 的回调函数即可。如下: - -```javaScript - export default { - // 只有 app 才会有 onLaunch 的生命周期 - onLaunch () { - // ... - }, - - // 捕获 app error - onError (err) { - console.log(err) - } - } -``` - - -### 4. 组件属性设置不生效解决办法 - -当重复设置某些属性为相同的值时,不会同步到`view`层。 例如:每次将`scroll-view`组件的`scroll-top`属性值设置为0,只有第一次能顺利返回顶部。 这和`props`的单向数据流特性有关,组件内部`scroll-top`的实际值改动后,其绑定的属性并不会一同变化。 - -解决办法有两种(以`scroll-view`组件为例): - -1.监听`scroll`事件,记录组件内部变化的值,在设置新值之前先设置为记录的当前值 - - - -```html - -``` - - -```javaScript -export default { - data() { - return { - scrollTop: 0, - old: { - scrollTop: 0 - } - } - }, - methods: { - scroll: function(e) { - this.old.scrollTop = e.detail.scrollTop - }, - goTop: function(e) { - this.scrollTop = this.old.scrollTop - this.$nextTick(function() { - this.scrollTop = 0 - }); - } - } -} - -``` - -2.监听scroll事件,获取组件内部变化的值,实时更新其绑定值 - -```html - -``` - - -```js - export default { - data() { - return { - scrollTop: 0, - } - }, - methods: { - scroll: function(e) { - // 如果使用此方法,请自行增加防抖处理 - this.scrollTop = e.detail.scrollTop - }, - goTop: function(e) { - this.scrollTop = 0 - } - } - } -``` - - -第二种解决方式在某些组件可能造成抖动,**推荐第一种解决方式**。 + + diff --git a/docs/vue3-basics.md b/docs/vue3-basics.md index 2e2dadba0..152c9f79c 100644 --- a/docs/vue3-basics.md +++ b/docs/vue3-basics.md @@ -7,9 +7,6 @@ -**Vue.js 是什么** - -Vue (读音 /vjuː/,类似于 `view`) 是一套用于构建用户界面的**渐进式框架**。与其它大型框架不同的是,`Vue` 被设计为可以自底向上逐层应用。 `Vue.js` 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 `DOM` 的系统,**只关注视图层,易于上手**。所有东西都是响应式的。 @@ -29,1651 +26,253 @@ Vue (读音 /vjuː/,类似于 `view`) 是一套用于构建用户界面的** - 组合API,加强API设计一致性,实现逻辑模块化和重用 - 加强TypeScript支持 - 暴露了自定义渲染API -- 提高自身可维护性 - - -## vue相比传统js的开发优势 - -在传统开发中,用原生的 JavaScript DOM 操作函数对 DOM 进行频繁操作的时候,浏览器要不停的渲染新的 DOM 树,导致页面看起来非常卡顿。 - -vue 是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和 DOM ,这样大大加快了访问速度和提升用户体验。 - - - -**vue的优势:** - -- 轻量级渐进式框架 -- 视图、数据和结构的分离 -- 响应式双向数据绑定 -- 组件化 -- 虚拟DOM -- 运行速度快,易于上手 -- 便于与第三方库或既有项目整合 - - - -### 文件类型变化 - -- 以前是.html文件,开发也是html,运行也是html。 -- 现在是.vue文件,开发是vue,经过编译后,运行时已经变成了js文件。 -- 现代前端开发,很少直接使用HTML,基本都是开发、编译、运行。所以 `uni-app` 有编译器、运行时的概念。 - - -### 文件内代码架构的变化 - -- 以前一个 `html` 大节点,里面有 `script` 和 `style` 节点; - -```html - - - - - - - - - - - -``` - - -- 现在 `template` 是一级节点,用于写tag组件, `script` 和 `style` 是并列的一级节点,也就是有3个一级节点。这个叫[vue单文件组件规范sfc](https://cn.vuejs.org/v2/guide/single-file-components.html)。 - -```html - - - -``` - - -### 外部文件引用方式变化 - -- 以前通过script src、link href引入外部的js和css; - -```html - - -``` - - -- 现在是es6的写法, `import` 引入外部的js模块(注意不是文件)或css; - -**js要require进来,变成了对象**。 -在hello uni-app的 `common` 目录有一个工具类 `util.js` ,可以在hello uni-app中搜索这个例子查看。hello uni-app示例代码可从 [github](https://github.com/dcloudio/hello-uniapp) 获取。 - - -```html - -``` - -而在这个 `util.js` 里,要把之前的 `function` 封装为对象的方法 - -```js - function formatTime(time) { - return time;//这里没写逻辑 - } - module.exports = { - formatTime: formatTime - } -``` - - -当然还有一些高级的用法 - -```js - - var dateUtils = require('../../../common/util.js').dateUtils; - - import * as echarts from '/components/echarts/echarts.simple.min.js'; -``` - -**css外部文件导入**。全局样式,在根目录下的 `app.vue` 里写入,每个页面都会加载 `app.vue` 里的样式。 - - -```html - -``` - - -**另外,vue支持组件导入,可以更方便的封装一个包括界面、js、样式的库**。[详见](/vue-components.md) - - -### 组件/标签的变化 - -以前是html标签,比如 `
` ,现在是内置组件,比如 `` 。 - -那么标签和组件有什么区别,不都是用尖括号包围起来一段英文吗? -- 其实标签是老的概念,标签属于浏览器内置的东西。 -- 但组件,是可以自由扩展的。类似你可以把一段js封装成函数或模块,你也可以把一个ui控件封装成一个组件。 - -`uni-app` 提供了一批[内置组件](https://uniapp.dcloud.io/component/README)。 - - -### js的变化 - - -- 以前的 DOM 操作,如果你想改变某个 DOM 元素的显示内容,比如一个view的显示文字:给view设id,然后js里通过选择器获取 DOM 元素,进一步通过js进行赋值操作,修改 DOM 元素的属性或值。 - -```html - - - - - - 123 - - - -``` - - -- 现在的做法,是vue的绑定模式,给这个 DOM 元素绑定一个js变量,在script中修改js变量的值,DOM 会自动变化,页面会自动更新渲染。 - - 前端改用 [MVVM](https://baike.baidu.com/item/MVVM/96310?fr=aladdin) (Model-View-ViewModel的简写)模式,简单来说,Model:代表数据模型,View:只专注视图UI处理,ViewModel:只处理业务和数据。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷,大幅减少代码行数,同时差量渲染性能更好。 - - `uni-app` 使用vue的数据绑定方式解决js和 DOM 界面交互的问题。 - - -```html - - -``` - - - - -## 在 uni-app 中使用差异 - -`uni-app` 在发布到H5时支持所有vue的语法;发布到App时,由于平台限制,无法实现全部vue语法,但 `uni-app` 仍是对vue语法支持度最高的跨端框架。 - -相比Web平台, Vue.js 在 `uni-app` 中使用差异主要集中在两个方面: - -- 新增:`uni-app` 除了支持Vue实例的生命周期,还支持[应用生命周期](https://uniapp.dcloud.io/collocation/frame/lifecycle?id=%e5%ba%94%e7%94%a8%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f)以及[页面生命周期](https://uniapp.dcloud.io/collocation/frame/lifecycle?id=%e9%a1%b5%e9%9d%a2%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f)。 -- 受限:相比web平台,在App端部分功能受限。 -- uni-app 完整支持 Vue 模板语法。 - - -[uni-app 项目支持 vue 3.0介绍,及升级指南](https://ask.dcloud.net.cn/article/37834) - - -`HBuilderX 3.2.5-alpha`新增在App平台支持 vue 3.0,至此 `uni-app` 项目对 vue 3.0 的支持情况如下: - -- H5/PC Web平台支持,编译器升级为`vite`。 -- App 平台:支持,编译器升级为`vite`,`nvue`暂不支持。 - - - -**注意事项** - -- vue3 响应式基于 `Proxy` 实现,不支持`iOS9`和`ie11`。 -- 暂不支持新增的 `Teleport`,`Suspense` 组件。 -- 暂不支持 `template` 下存在多个根节点。 -- 目前 `HBuilderX 3.2` 起已预置,之前的版本只能使用cli方式。 - - - - -## 模板语法 - -`Vue.js` 使用了基于 `HTML` 的模板语法,允许开发者声明式地将 `DOM` 绑定至底层组件实例的数据。 -所有 `Vue.js` 的模板都是合法的 `HTML`,所以能被遵循规范的浏览器和 `HTML` 解析器解析。 - -在底层的实现上,`Vue` 将模板编译成虚拟 `DOM` 渲染函数。结合响应性系统,`Vue` 能够智能地计算出最少需要重新渲染多少组件,并把 `DOM` 操作次数减到最少。 - - -### 插值 - -#### 文本 - -数据绑定最常见的形式就是文本插值: - -```html - - -``` - -{{msg}}里的内容将会被替代为对应数据对象上msg的值。无论何时,绑定的数据对象上msg发生了改变,插值处的内容都会更新。 - - -#### 使用 JavaScript 表达式 - - -迄今为止,在我们的模板中,我们一直都只绑定简单的 `property` 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 `JavaScript` 表达式支持。 - -**示例一** - -```html - - -``` - - -**示例二** - -```html - - - -``` - - -这些表达式会在所属 Vue 实例的数据作用域下作为 `JavaScript` 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。 - -**错误示例** -```html - - -``` - - - - -> 模板表达式都被放在沙盒中,只能访问**全局变量的一个白名单**: -> - `Infinity` -> - `undefined` -> - `NaN` -> - `isFinite` -> - `isNaN` -> - `parseFloat` -> - `parseInt` -> - `decodeURI` -> - `decodeURIComponent` -> - `encodeURI` -> - `encodeURIComponent` -> - `Math` -> - `Number` -> - `Date` -> - `Array` -> - `Object` -> - `Boolean` -> - `String` -> - `RegExp` -> - `Map` -> - `Set` -> - `JSON` -> - `Intl` -> - `BigInt` -> -> 你不应该在模板表达式中试图访问用户定义的全局变量。 - - - -### 指令 - -指令是带有 v- 前缀的特殊属性。 - -- 指令属性的值预期是**单个 `JavaScript` 表达式** (`v-for` 和 `v-on` 是例外情况,稍后我们再讨论)。 -- 指令的作用是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 `DOM` 。 -- 一些指令能够接收一个“参数”,在指令名称之后以冒号( : )表示。 - - -#### v-bind - -动态地绑定一个或多个属性,`v-bind`缩写为‘ : ’,可以用于响应式地更新 `HTML attribute`: - -```html - - - - - - -``` - -在这里 `src` 是参数,告知 `v-bind` 指令将该元素的 `src` attribute 与表达式 `imgUrl` 的值绑定。 - -如果 `isButtonDisabled` 的值是 `null` 或 `undefined`,则 `disabled` attribute 甚至不会被包含在渲染出来的 `button` 元素中。 - - -#### v-on - -v-on 指令,它用于监听 `DOM` 事件。v-on缩写为‘ @ ’,下文简称为 `@事件` - -```html - - 点击 - - 点击 -``` - - -#### v-once - -只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。 - -和前端框架中的理解不同,客户端里要实现复用的逻辑,会标记模板节点的状态,添加了 `v-once` 能保证节点只渲染一次,但是并不一定能优化渲染性能,反而可能会拖慢客户端复用节点时的比对效率。 - -```html - - This will never change: {{msg}} - - - comment - {{msg}} - -``` - - -#### v-html - -更新元素的 [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) 。 - -- 注意:**内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。** -- 如果试图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。 - - -跨端的富文本处理方案详见:[https://ask.dcloud.net.cn/article/35772](https://ask.dcloud.net.cn/article/35772) - -```html - - -``` - - - -## Data 选项 - -`data` 选项已标准化为只接受**返回一个初始数据对象的函数**(注意函数内返回的数据对象不要直接引用函数外的对象);否则页面关闭时,数据不会自动销毁,再次打开该页面时,会显示上次数据。 - -```js - //正确用法,使用函数返回对象 - data() { - return { - title: 'Hello' - } - } - - //错误写法,会导致再次打开页面时,显示上次数据 - data: { - title: 'Hello' - } - - //错误写法,同样会导致多个组件实例对象数据相互影响 - const obj = { - title: 'Hello' - } - data() { - return { - obj - } - } -``` - - - -## Class 与 Style 绑定 - - -### 绑定 HTML Class - - -**对象语法** - - -我们可以传给 `:class` (`v-bind:class` 的简写) 一个对象,实现动态地切换 `class`。 - -也可以在对象中传入更多字段来动态切换多个 `class`。此外,`v-bind:class` 指令也可以与普通的 `class` 共存。 - - -```html - - - -``` - -渲染结果为 - -```html - -``` - -当 `isActive` 或者 `hasError` 变化时,class 列表将相应地更新。例如,如果 `hasError` 的值为 `true` ,class 列表将变为 `static active text-danger`。 - - - -**数组语法** - -可以把一个数组传给 `v-bind:class`,以应用一个 `class` 列表。 - -```html - - - -``` - - -渲染的结果为: - -```html - -``` - -如果你想根据条件切换列表中的 class,可以使用三元表达式: - - -```html - -``` - - -这样写将始终添加 `errorClass`,但是只有在 `isActive` 为 `truthy` 时才添加 `activeClass`。 - -> 在 `JavaScript` 中,`truthy`(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为 假值(即除 `false`、0、""、`null`、`undefined` 和 `NaN` 以外皆为真值)。 - - -不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法: - -```html - - - -``` - -**注意:以:style=""这样的方式设置px像素值,其值为实际像素,不会被编译器转换。** - - -此外还可以用计算属性 `computed` 方法生成 `class` 或者 `style` 字符串,插入到页面中,举例说明: - -```html - - - -``` - - - -### 绑定内联样式 - -**对象语法** - -:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 `JavaScript` 对象。CSS property 名可以用驼峰式 (`camelCase`) 或短横线分隔 (`kebab-case`,记得用引号括起来) 来命名: - -```html - - -``` - - -直接绑定到一个样式对象通常更好,这会让模板更清晰: - -```html - - -``` - -同样的,对象语法常常结合返回对象的计算属性使用。 - - -**数组语法** - -`:style` 的数组语法可以将多个样式对象应用到同一个元素上: - -```html - - -``` - - -**自动添加前缀** - -在 `:style` 中使用需要 (浏览器引擎前缀) [vendor prefixesa](https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix) 的 `CSS property` 时,如 `transform`,`Vue` 将自动侦测并添加相应的前缀。 - - - -**多重值** - -可以为 `style` 绑定中的 `property` 提供一个包含多个值的数组,常用于提供多个带前缀的值,例如: - -```html - -``` - -这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 `flexbox`,那么就只会渲染 `display: flex`。 - - -## 条件渲染 - -### v-if和v-else - -`v-if` 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 `truthy` 值的时候被渲染。 -使用 `v-else` 指令来表示 `v-if` 的“else 块”。 -`v-else` 元素必须紧跟在带 `v-if` 或者 `v-else-if` 的元素的后面,否则它将不会被识别。 - -> 在 `JavaScript` 中,`truthy`(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为 假值(即除 `false`、0、""、`null`、`undefined` 和 `NaN` 以外皆为真值)。 - -```html - - -``` - - -`v-else-if`,顾名思义,充当 v-if 的“else-if 块”,可以连续使用: - - -```html - - -``` - -类似于 `v-else` ,`v-else-if` 也必须紧跟在带 `v-if` 或者 `v-else-if` 的元素之后。 - - -### 条件渲染分组 - -因为 `v-if` 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢? - -此时可以把一个 `template` 元素当做不可见的包裹元素,并在上面使用 `v-if`。最终的渲染结果将不包含 `template` 元素。 - - -```html - -``` - - -### v-show - -另一个用于根据条件展示元素的选项是 `v-show` 指令。用法大致一样: - -```html - Hello! -``` - -不同的是带有 `v-show` 的元素始终会被渲染并保留在 `DOM` 中。`v-show` 只是简单地切换元素的 `CSS` 属性的 `display` 。 - -> 注意,v-show 不支持 template 元素,也不支持 v-else。nvue 页面不支持 v-show。 - - -### v-if 和 v-show 区别 - - -`v-if` 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 - -`v-if` 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 - -相比之下,`v-show` 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,来控制元素的显示和隐藏。 - -**根据应用场景选择** - -- `v-if` 有更高的切换开销,如果在运行时条件很少改变,则使用 v-if 较好。 -- `v-show` 有更高的初始渲染开销。如果需要非常频繁地切换,则使用 v-show 较好。 - - -**注意** - -- 不推荐同时使用 `v-if` 和 `v-for`。 -- 当 `v-if` 与 `v-for` 一起使用时,**`v-if` 具有比 `v-for` 更高的优先级**。 - - -## 列表渲染 - -### 在 v-for 里使用数组 - -v-for 指令可以实现基于一个数组来渲染一个列表。 - -- `v-for` 指令需要使用 `item in items` 形式的特殊语法,其中 `items` 是源数据数组,而 `item` 则是被迭代的数组元素的别名。 - - 在 v-for 块中,我们可以访问所有父作用域的 `property` - - 第一个参数 `item` 则是被迭代的数组元素的别名。 - - 第二个参数,即当前项的索引 `index` ,是可选的。 - -```html - - -``` - -结果: - -```html - Parent - 0 - Foo - Parent - 1 - Bar -``` - - -### 在 v-for 里使用对象 - -你也可以用 v-for 来遍历一个对象的 `property`。 - -- 第一个参数 `value` 是被迭代的对象元素的属性值。 -- 第二个参数为 `property` 名称 (也就是键名)。 -- 第三个参数作为索引。 - -```html - - -``` - - -结果: - -```html - 0.title: How to do lists in Vue, - 1.author: Jane Doe, - 2.publishedAt: 2021-05-10 -``` - - -> 在遍历对象时,会按 `Object.keys()` 的结果遍历,但是不能保证它在不同 `JavaScript` 引擎下的结果都一致。 - - -### 列表渲染分组 - -类似于 `v-if`,你也可以利用带有 `v-for` 的 `template` 来循环渲染一段包含多个元素的内容。比如: - -```html - -``` - - -### 维护状态 - - -当 `Vue` 正在更新使用 `v-for` 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,`Vue` 将不会移动 `DOM` 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。 - - -这个默认的模式是高效的,但是**只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出**。 - - -为了给 `Vue` 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 `key` attribute: - -```html - - - -``` - -建议尽可能在使用 `v-for` 时提供 `key` attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。 - -- 如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。 -- 而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除/销毁 key 不存在的元素。 -- 有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。 - -> 不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。 -> -> 如不提供 :key,会报一个 `warning`, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。 - -示例: - -```html - - -``` - - -### 注意事项 - -- 在H5平台 使用 v-for 循环整数时和其他平台存在差异,如 `v-for="(item, index) in 10"` 中,在H5平台 item 从 1 开始,其他平台 item 从 0 开始,可使用第二个参数 index 来保持一致。 -- 在非H5平台 循环对象时不支持第三个参数,如 `v-for="(value, name, index) in object"` 中,index 参数是不支持的。 - - - -### 结合 `