参考资料

基础

简介

  • 单文件组件 SFC
  • API分隔

    • 选项式
    • 组合式

      创建一个应用

      通过 createApp 创建 应用实例

      根组件

  • 传入createApp的是根组件

  • 多数真实的应用都是由一颗嵌套的、可重用的组件树组成的。

    挂载应用

  • 应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串:

    应用配置

    ```javascript app.config.errorHandler = (err) => { / 处理错误 / }

app.component(‘TodoDeleteButton’, TodoDeleteButton) // 注册组件

  1. <a name="Jt45x"></a>
  2. ### 多个应用实例
  3. <a name="sq01m"></a>
  4. ## 模板语法
  5. <a name="pq8hH"></a>
  6. ### 文本插值
  7. - “Mustache”语法 (即双大括号)
  8. <a name="CdQC9"></a>
  9. ### 原始HTML
  10. ```javascript
  11. <p>Using text interpolation: {{ rawHtml }}</p>
  12. <p>Using v-html directive: <span v-html="rawHtml"></span></p>

Atrribute绑定

  • 如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除。

    1. <div v-bind:id="dynamicId"></div>
    2. <div :id="dynamicId"></div>

    布尔型 Attribute

  • 当 isButtonDisabled 为真值或一个空字符串 (即

  1. <a name="LM59u"></a>
  2. ### 使用 JavaScript 表达式
  3. - 在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:
  4. - 在文本插值中 (双大括号)
  5. - 在任何 Vue 指令 (以 v- 开头的特殊 attribute) attribute 的值中
  6. - 仅支持表达式
  7. - 调用函数
  8. ```html
  9. <span :title="toTitleDate(date)">
  10. {{ formatDate(date) }}
  11. </span>
  • 受限的全局访问

  • 带v-的特殊atrribute

  • 指令 attribute 的期望值为一个 JavaScript 表达式 (之后要讨论到的 v-for 和 v-on 将会是例外)。

    参数

    动态参数

  • 动态参数值的限制

    • 动态参数期望结果为一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。任何其他非字符串的值都将触发一个警告。
  • 动态参数语法的限制
    • 如果你需要传入一个复杂的动态参数,我们推荐使用计算属性替换复杂的表达式,
    • 避免在名称中使用大写字母,因为浏览器会强制将其转换为小写: ```html

  1. <a name="cm4iD"></a>
  2. ### 修饰符
  3. - .prevent 修饰符会告知 v-on 指令对触发的事件调用 event.preventDefault():
  4. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/1728028/1645001244408-2ce7c779-f172-4a14-9fb5-63046a8c4120.png#clientId=ue5794e29-8e05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=220&id=u73287bc5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=440&originWidth=1376&originalType=binary&ratio=1&rotation=0&showTitle=false&size=64651&status=done&style=none&taskId=uaa1c665d-5148-462c-b9f3-6c23fb66adc&title=&width=688)
  5. <a name="zOTnC"></a>
  6. ## 响应式基础
  7. <a name="t7QHk"></a>
  8. ### 声明响应式状态
  9. ```javascript
  10. export default {
  11. data() {
  12. return {
  13. someObject: {}
  14. }
  15. },
  16. mounted() {
  17. const newObject = {}
  18. this.someObject = newObject
  19. console.log(newObject === this.someObject) // false 和 Vue 2 不同,
  20. //原始的 newObject 不会变为响应式:确保始终通过 this. 来访问响应式状态。
  21. }
  22. }

声明方法

  • Vue 自动为 methods 中的方法绑定了永远指向组件实例的 this。这确保了方法在作为事件监听器或回调函数时始终保持正确的 this。你不应该在定义 methods 时使用箭头函数,因为这会阻止 Vue 的自动绑定。

    1. export default {
    2. methods: {
    3. increment: () => {
    4. // BAD: no `this` access here!
    5. }
    6. }
    7. }

    DOM 更新时机

  • 注意 DOM 的更新并不是同步的。相反,Vue 会将它们推入更新循环的 “下个 tick” 执行以确保无论改变了多少个状态,每个需要更新的组件都只更新一次。

  • 若要等待一个状态改变后的 DOM 更新完成,你可以使用 nextTick() 这个全局 API: ```javascript import { nextTick } from ‘vue’

export default { methods: { increment() { this.count++ nextTick(() => { // access updated DOM }) } } }

  1. <a name="qdAbY"></a>
  2. #### 深层响应性
  3. - 在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。
  4. - 也可以创建一个 [浅层 ref](https://staging-cn.vuejs.org/api/reactivity-advanced.html#shallowref) 和 [浅层响应式对象](https://staging-cn.vuejs.org/api/reactivity-advanced.html#shallowreactive)。它们仅在顶层具有响应性,一般仅在某些特殊场景中需要。
  5. ```javascript
  6. export default {
  7. data() {
  8. return {
  9. obj: {
  10. nested: { count: 0 },
  11. arr: ['foo', 'bar']
  12. }
  13. }
  14. },
  15. methods: {
  16. mutateDeeply() {
  17. // 以下都会按照期望工作
  18. this.obj.nested.count++
  19. this.obj.arr.push('baz')
  20. }
  21. }
  22. }

有状态方法

  • 防止不同实例的方法彼此影响
    1. export default {
    2. created() {
    3. // 每个实例都有了自己的预置防抖的处理函数
    4. this.debouncedClick = _.debounce(this.click, 500)
    5. },
    6. unmounted() {
    7. // 最好是在组件卸载时
    8. // 清除掉防抖计时器
    9. this.debouncedClick.cancel()
    10. },
    11. methods: {
    12. click() {
    13. // ... 对点击的响应 ...
    14. }
    15. }
    16. }

    计算属性

    ```javascript

export default { data() { return { author: { name: ‘John Doe’, books: [ ‘Vue 2 - Advanced Guide’, ‘Vue 3 - Basic Guide’, ‘Vue 4 - The Mystery’ ] } } }, computed: { // 一个计算属性的 getter publishedBooksMessage() { // this 指向当前组件实例 return this.author.books.length > 0 ? ‘Yes’ : ‘No’ } } }

……

Has published books:

{{ publishedBooksMessage }}

  1. <a name="euig2"></a>
  2. ### 计算属性缓存 vs 方法
  3. - **计算属性值会基于其响应式依赖被缓存,**一个计算属性仅会在其响应式依赖更新时才重新计算
  4. - 相比之下,方法调用**总是**会在重渲染发生时再次执行函数。
  5. <a name="uvNcH"></a>
  6. ### 可写计算属性
  7. ```javascript
  8. export default {
  9. data() {
  10. return {
  11. firstName: 'John',
  12. lastName: 'Doe'
  13. }
  14. },
  15. computed: {
  16. fullName: {
  17. // getter
  18. get() {
  19. return this.firstName + ' ' + this.lastName
  20. },
  21. // setter
  22. set(newValue) {
  23. // 注意:我们这里使用的是解构赋值语法
  24. [this.firstName, this.lastName] = newValue.split(' ')
  25. }
  26. }
  27. }
  28. }

计算函数不应有副作用

计算属性的计算函数应只做计算而没有任何其他的副作用,这一点非常重要,请务必牢记。举个例子,不要在计算函数中做异步请求或者更改 DOM!一个计算属性的声明中描述的是如何根据其他值派生一个值。因此计算函数的职责应该仅为计算和返回该值。在之后的指引中我们会讨论如何使用监听器根据其他响应式状态的变更来创建副作用。

避免直接修改计算属性值

从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。因此更改快照是没有意义的,因此,计算属性的返回值应该被视为只读的,并且永远不会发生突变。应该更新它所依赖的源状态,以触发新一次计算。

类与样式绑定

绑定HTML对象

绑定对象

  1. #######
  2. <div :class="{ active: isActive }"></div>
  3. data() {
  4. return {
  5. isActive: true,
  6. hasError: false
  7. }
  8. }
  9. ######
  10. <div :class="classObject"></div>
  11. data() {
  12. return {
  13. classObject: {
  14. active: true,
  15. 'text-danger': false
  16. }
  17. }
  18. }
  19. ####
  20. <div :class="classObject"></div>
  21. data() {
  22. return {
  23. isActive: true,
  24. error: null
  25. }
  26. },
  27. computed: {
  28. classObject() {
  29. return {
  30. active: this.isActive && !this.error,
  31. 'text-danger': this.error && this.error.type === 'fatal'
  32. }
  33. }
  34. }

绑定数组

  1. data() {
  2. return {
  3. activeClass: 'active',
  4. errorClass: 'text-danger'
  5. }
  6. }
  7. <div :class="[activeClass, errorClass]"></div>
  8. <div :class="[isActive ? activeClass : '', errorClass]"></div>
  9. <div :class="[{ active: isActive }, errorClass]"></div>

和组件配合

  • 使用组件时渲染后会自动叠加属性

    • 组件

      1. <!-- child component template -->
      2. <p class="foo bar">Hi!</p>
    • 使用组件

      1. <my-component class="baz boo"></my-component>
    • 渲染后

      1. <p class="foo bar baz boo">Hi</p>

      绑定内联样式

      绑定对象

  • camelCase 与 kebab-cased 形式 ```javascript data() { return { activeColor: ‘red’, fontSize: 30 } }

///////////// data() { return { styleObject: { color: ‘red’, fontSize: ‘13px’ } } }

  1. <a name="iXdQq"></a>
  2. #### 绑定数组
  3. <a name="JY6rL"></a>
  4. #### 自动前缀
  5. - 当你在 :style 中使用了需要[浏览器特殊前缀](https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix)的 CSS 属性时,Vue 会自动为他们加上相应的前缀。
  6. <a name="qQ3DX"></a>
  7. #### 样式多值
  8. <a name="MWNEa"></a>
  9. ## 条件渲染
  10. <a name="ugV0c"></a>
  11. ### v-if
  12. <a name="UI5RX"></a>
  13. ### v-else
  14. <a name="cO7r8"></a>
  15. ### v-else-if
  16. ```javascript
  17. <div v-if="type === 'A'">
  18. A
  19. </div>
  20. <div v-else-if="type === 'B'">
  21. B
  22. </div>
  23. <div v-else-if="type === 'C'">
  24. C
  25. </div>
  26. <div v-else>
  27. Not A/B/C
  28. </div>