Vue记录

Vue记录。~~~typescript // const 组件名 = () => import('组件路径');

其他

路由

路由懒加载组件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// const 组件名 = () => import('组件路径');
const Home = () => import('@/componnets/home');
const Index = () => import('@/components/index');
 
{
  path: '/home',
  name: 'home',
  component: Home
}, {
  path: '/index',
  name: 'index',
  component: Index
}

模板形式

选项式更容易理解,但推荐组合式

选项式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件处理器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

组合式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

ES 模块

在 Html 的 script 标签中,原来只能添加简单的 JS 语句,现在添加属性 type="module" 之后就可以使用 import 语句。

未使用 ES 模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<body>
    <div id="app">
        
    </div>
</body>
<script>
	const { createApp, ref } = Vue

    createApp({
        setup() {
            const message = ref('Hello vue!')
            return {
                message
            }
        }
    }).mount('#app')
</script>

使用 ES 模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<div id="app">{{ message }}</div>

<script type="module">
    import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

    createApp({
        setup() {
            const message = ref('Hello Vue!')
            return {
                message
            }
        }
    }).mount('#app')
</script>

异常捕捉

1
2
3
4
5
6
7
var app = createApp(App)

app.use(Antd).mount('#app')

app.config.errorHandler = (err, instance, info) => {
  // 处理错误,例如:报告给一个服务
}

全局属性

1
2
3
4
5
var app = createApp(App)

app.use(Antd).mount('#app')

app.config.globalProperties.msg = 'hello'

这使得 msg 在应用的任意组件模板上都可用,并且也可以通过任意组件实例的 this 访问到:

1
2
3
4
5
export default {
  mounted() {
    console.log(this.msg) // 'hello'
  }
}

动态绑定多个值

如果你有像这样的一个包含多个 attribute 的 JavaScript 对象:

1
2
3
4
const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}

通过不带参数的 v-bind,你可以将它们绑定到单个元素上:

template

1
<div v-bind="objectOfAttrs"></div>

等待DOM渲染更新

1
2
3
4
5
6
7
import { nextTick } from 'vue'

async function increment() {
  count.value++
  await nextTick()
  // 现在 DOM 已经更新了
}

优化

避免不必要的组件抽象

有些时候我们会去创建无渲染组件或高阶组件 (用来渲染具有额外 props 的其他组件) 来实现更好的抽象或代码组织。虽然这并没有什么问题,但请记住,组件实例比普通 DOM 节点要昂贵得多,而且为了逻辑抽象创建太多组件实例将会导致性能损失。

ref 和 reactive

reactive() API 有一些局限性:

  1. 有限的值类型:它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumberboolean 这样的原始类型

  2. 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:

    js

    1
    2
    3
    4
    5
    
    let state = reactive({ count: 0 })
    
    // 上面的 ({ count: 0 }) 引用将不再被追踪
    // (响应性连接已丢失!)
    state = reactive({ count: 1 })
    
  3. 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:

    js

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    const state = reactive({ count: 0 })
    
    // 当解构时,count 已经与 state.count 断开连接
    let { count } = state
    // 不会影响原始的 state
    count++
    
    // 该函数接收到的是一个普通的数字
    // 并且无法追踪 state.count 的变化
    // 我们必须传入整个对象以保持响应性
    callSomeFunction(state.count)
    

由于这些限制,我们建议使用 ref() 作为声明响应式状态的主要 API。

方法vs计算属性

计算属性值会基于其响应式依赖被缓存,重复使用的属性应该以计算属性的方式存在。

1
2
3
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})

注意:

因为 Date.now() 并不是一个响应式依赖,下面的计算属性永远不会更新:

1
const now = computed(() => Date.now())

根据属性渲染样式

可以绑定一个返回对象的计算属性。这是一个常见且很有用的技巧:

1
2
3
4
5
6
7
const isActive = ref(true)
const error = ref(null)

const classObject = computed(() => ({
    active: isActive.value && !error.value,
    'text-danger': error.value && error.value.type === 'fatal'
}))
1
<div :class="classObject"></div>
Licensed under CC BY-NC-SA 4.0
Gear(夕照)的博客。记录开发、生活,以及一些不足为道的思考……