#根据官网看vue3的变化
#Composition API
目的:把以前放在computed、methods、watch内的代码组合一起放在同一个地方,方便阅读与理解,以前是散装的,现在融合。
方法:setup
参数:
- props
- context
注意点:
- 没有this
- 只能访问组件内的props,通过参数获取
defineComponent: 定义Vue组件
内部可以使用的方法
- ref: 返回一个响应式且可变的ref对象,可以用于组件实例ref实例
- toRefs: 创建对prop的响应式引用
- computed: 计算属性
- reactive: 对象响应式,与传入的对象一致
<template>
  <button type="button" @click="addSize">count is: {{ count }}</button>
  <p>{{ size }}</p>
  <p>{{ allMsg }}</p>
  <p>{{ person.age }}</p>
</template>
<script lang="ts">
import { ref, defineComponent, onMounted, watch, toRefs, computed, reactive } from 'vue'
type Size = 'sm' | 'md' | 'lg'
export default defineComponent({
  props: {
    msg: {
      type: String,
      default: ''
    }
  },
  setup: (props, context) => {
    // 上下文中的三个属性
    console.log(context.attrs)
    console.log(context.slots)
    console.log(context.emit)
    
    // 响应式
    const { msg } = toRefs(props)
    const size = ref<Size>('md')
    const person = reactive({ age: 18 })
    const addSize = () => {
      size.value = 'lg'
    }
    const update = () => {
      size.value = 'sm'
      window.console.log(`prop msg: ${msg.value}`)
    }
    // vue2的mounted方法
    onMounted(update)
    // vue2的computed方法
    const allMsg = computed(() => size.value + msg.value);
    // vue2的watch方法
    watch(size, (newSize, oldSize) => {
      if (newSize === 'lg') {
        console.log(`new value is ${newSize}, old value is ${oldSize}`)
      }
    })
    return { size, addSize, allMsg, person }
  }
})
</script>
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
内部生命周期函数
- onBeforeMount
- onMounted
- onBeforeMount
- onBeforeUpdate
- onBeforeMount
- onUpdated
<script lang="ts">
import { defineComponent, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated } from 'vue'
export default defineComponent({
  setup: () => {
    onBeforeMount(() => {
      console.log('beforeMount')
    })
    onMounted(() => {
      console.log('mounted')
    })
    onBeforeUpdate(() => {
      console.log('beforeUpdate')
    })
    onUpdated(() => {
      console.log('update')
    })
    onBeforeUnmount(() => {
      console.log('beforeUnmounted')
    })
    onUnmounted(() => {
      console.log('unmounted')
    })
    return {  }
  }
})
</script>
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
30
31
32
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
30
31
32
provide&inject
App.vue
<template>
  <HelloWorld />
</template>
<script lang="ts">
import { defineComponent, provide, reactive, ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
export default defineComponent({
  name: 'App',
  components: {
    HelloWorld
  },
  setup() {
    const num = ref(0)
    const person = reactive({ age: 18 })
    const changePerson = () => {
      person.age = 19;
    }
    
    provide('num', num)
    provide('person', person)
    provide('changePerson', changePerson)
  }
})
</script>
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
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
HelloWorld.vue
<template>
  <button @click="changePerson">test</button>
  <p>inject num is {{ num }}, inject person age is {{ person.age }}</p>
</template>
<script lang="ts">
import { defineComponent, inject } from 'vue'
export default defineComponent({
  setup: () => {
    const num = inject('num')
    const person = inject('person')
    const changePerson = inject('changePerson')
    return { num, person, changePerson }
  }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ref实例
<template>
  <div ref="root">
    root node
  </div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue'
export default defineComponent({
  setup: () => {
    const root = ref(null)
    onMounted(() => {
      console.log(root.value)
    })
    return { root }
  }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ref+v-for
<template>
  <ul>
    <li v-for="(num, index) in nums" :key="num" :ref="el => numRef(el, index)">
      {{ num }}
    </li>
  </ul>
</template>
<script lang="ts">
import { defineComponent, onBeforeUpdate, reactive, ref } from 'vue'
export default defineComponent({
  setup: () => {
    const nums = reactive([1, 2, 3])
    let numRefs = ref<HTMLLIElement[]>([])
    const numRef = (el: HTMLLIElement, idx: number) => {
      numRefs.value[idx] = el
    }
    // 动态更新
    onBeforeUpdate(() => {
      numRefs.value = []
    })
    return { nums, numRefs, numRef }
  }
})
</script>
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
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
watchEffect
<template>
  <div ref="root">
    root node
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, watchEffect } from 'vue'
export default defineComponent({
  setup: () => {
    const root = ref(null)
    // 监听
    watchEffect(() => {
      console.log(root.value)
    }, {
      flush: 'post' // 是否在更新之后运行watch,post在dom更新之后
    })
    return { root }
  }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
teleport:允许开发者控制渲染的DOM节点
<template>
    <button @click="modalOpen = true">open</button>
    <teleport to="body">
        <div v-if="modalOpen">
            <div>模态框</div>
            <button @click="modalOpen = false">close</button>
        </div>
    </teleport>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
    setup() {
        const modalOpen = ref(false);
        return {
            modalOpen
        }
    }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23