1、Options API==>Composition API

3、新特性 - 图1
3、新特性 - 图2

2、setup

  1. import {toRefs} from 'vue'
  2. export default {
  3. name: 'demo',
  4. props:{
  5. name: String,
  6. },
  7. // setup()作为在组件内使用Composition API的入口点。
  8. // 执行时机是在beforeCreate和created之间,不能使用this获取组件的其他变量,
  9. // 而且不能是异步。setup返回的对象和方法,都可以在模版中使用。
  10. setup(props, context){
  11. // 这里需要使用toRefs来进行解构
  12. // 这里的props与vue2基本一致,当然这里的name也可以直接在template中使用
  13. const { name }=toRefs(props);
  14. console.log(name.value);
  15. // context是一个上下文对象
  16. //【从原来 2.x 中 this 选择性地暴露了一些 property(attrs/emit/slots)】
  17. // 属性,同vue2的 $attrs
  18. console.log(context.attrs);
  19. // 插槽
  20. console.log(context.slots);
  21. // 事件,同vue2的 $emit
  22. console.log(context.emit);
  23. // 生命周期钩子
  24. onMounted(() => {})
  25. }
  26. }

注意点:

  • 注意 props 对象是响应式的,watchEffect 或 watch 会观察和响应 props 的更新,不要解构 props 对象,那样会使其失去响应性
  • attrs 和 slots 都是内部组件实例上对应项的代理,可以确保在更新后仍然是最新值。所以可以解构,无需担心后面访问到过期的值
  • this setup()中不可用。由于 setup() 在解析 2.x 选项前被调用,setup() 中的 this 将与 2.x 选项中的 this 完全不同。同时在 setup() 和 2.x 选项中使用 this 时将造成混乱

    3、ref和reactive

    |

    | ref | reactive | | —- | —- | —- | | 入参 | 基本类型 | 引用类型 | | 返回值 | 响应式且可变的 ref 对象 | 响应式代理(Proxy) | | 访问方式 | 1.ref 对象拥有一个指向内部值的单一属性.value
    2.在dom和setup()的return中会自动解套
    3.ref 作为 reactive 对象的 property 被访问或修改时,也将自动解套 | 直 |

A、ref简单的计数

  1. <template>
  2. <div>
  3. <p><button @click="add">{{count}}</button></p>
  4. </div>
  5. </template>
  6. <script>
  7. import {ref} from 'vue'
  8. export default {
  9. setup(){
  10. // ref 对我们的值创建了一个响应式引用
  11. var count = ref(0);
  12. const add = ()=>{
  13. count.value++
  14. }
  15. return {
  16. count, // return返回会自动解套【在模板中不需要.value】
  17. add
  18. }
  19. }
  20. }
  21. </script>

B、reactive

  1. // reactive
  2. // 接收一个普通对象然后返回该普通对象的响应式代理
  3. <template>
  4. <div>
  5. <p><button @click="state.add">{{state.count}}</button></p>
  6. </div>
  7. </template>
  8. <script>
  9. import {reactive} from 'vue'
  10. export default {
  11. setup(){
  12. var state = reactive({
  13. count:1,
  14. add(){
  15. state.count++
  16. }
  17. })
  18. return {
  19. state
  20. }
  21. }
  22. }
  23. </script>

Tips:不能对reactive执行解构

问题 & 注意点: 因为reactive是组合函数【对象】,所以必须始终保持对这个所返回对象的引用以保持响应性,不能解构该对象或者展开

C、toRefs

用来提供解决此约束的办法——它将响应式对象的每个 property 都转成了相应的 ref【把对象转成了ref】

  1. <template>
  2. <div>
  3. <p><button @click="add">{{count}}</button></p>
  4. </div>
  5. </template>
  6. <script>
  7. import {reactive, toRefs} from 'vue'
  8. export default {
  9. setup(){
  10. const state = reactive({
  11. count:1,
  12. add(){
  13. state.count++
  14. }
  15. })
  16. const refState = toRefs(state)
  17. return {
  18. ...refState
  19. }
  20. }
  21. }
  22. </script>

4、自定义Hooks

A、Hooks/CountHook.js

  1. <template>
  2. <div>
  3. <p><button @click="add">{{count}}</button></p>
  4. </div>
  5. </template>
  6. <script>
  7. import {reactive, toRefs} from 'vue'
  8. export default {
  9. setup(){
  10. const state = reactive({
  11. count:1,
  12. add(){
  13. state.count++
  14. }
  15. })
  16. const refState = toRefs(state)
  17. return {
  18. ...refState
  19. }
  20. }
  21. }
  22. </script>

B、父页面

  1. <template>
  2. <div>
  3. <button @click="add">{{count}}</button>
  4. </div>
  5. </template>
  6. <script>
  7. import {useCounter} from './Hooks/CityHook'
  8. export default {
  9. setup(){
  10. return {
  11. ...useCounter()
  12. }
  13. }
  14. }
  15. </script>

5、计算和侦听

A、计算属性

  1. <template>
  2. <div>
  3. <button @click="add">{{count}}</button>
  4. <p>{{double}}</p>
  5. </div>
  6. </template>
  7. <script>
  8. import { ref } from '@vue/reactivity'
  9. import { computed } from '@vue/runtime-core';
  10. export default {
  11. setup(){
  12. const count = ref(0);
  13. const add=()=>{
  14. count.value++
  15. }
  16. //不支持修改,只读属性
  17. const double = computed(()=>{
  18. return count.value*2
  19. })
  20. return {
  21. count,
  22. add,
  23. double
  24. }
  25. }
  26. }
  27. </script>

B、计算属性get-set

  1. <template>
  2. <div>
  3. <input type="checkbox" v-model="checkState">
  4. </div>
  5. </template>
  6. <script>
  7. import { ref,computed } from 'vue'
  8. export default {
  9. setup(){
  10. let state = ref(false);
  11. let checkState = computed({
  12. get:()=>state.value,
  13. set:(val)=>{
  14. state.value = val
  15. }
  16. })
  17. return {
  18. checkState
  19. }
  20. }
  21. }
  22. </script>

C、watch ref监听一个值

  1. <template>
  2. <div><button @click="add">{{count}}</button></div>
  3. </template>
  4. <script>
  5. import { ref } from '@vue/reactivity'
  6. import { watch } from '@vue/runtime-core';
  7. export default {
  8. setup(){
  9. let count = ref(0);
  10. const add = ()=>{
  11. count.value++
  12. }
  13. watch(count,(count,prevCount)=>{
  14. console.log(count,prevCount)
  15. })
  16. return {
  17. count,
  18. add
  19. }
  20. }
  21. }
  22. </script>

D、watch reactive

  1. <template>
  2. <div><button @click="add">{{count}}</button></div>
  3. </template>
  4. <script>
  5. import { reactive,toRefs } from '@vue/reactivity'
  6. import { watch } from '@vue/runtime-core';
  7. export default {
  8. setup(){
  9. let state = reactive({
  10. count:1,
  11. add(){
  12. state.count++
  13. }
  14. })
  15. let refState = toRefs(state);
  16. watch(state,()=>{
  17. console.log(state.count)
  18. })
  19. return {
  20. ...refState
  21. }
  22. }
  23. }
  24. </script>

优化 箭头函数

  1. <template>
  2. <div><button @click="add">{{count}}</button></div>
  3. </template>
  4. <script>
  5. import { reactive,toRefs } from '@vue/reactivity'
  6. import { watch } from '@vue/runtime-core';
  7. export default {
  8. setup(){
  9. let state = reactive({
  10. count:1,
  11. add(){
  12. state.count++
  13. }
  14. })
  15. let refState = toRefs(state);
  16. watch(()=>state.count,()=>{
  17. console.log(state.count)
  18. })
  19. return {
  20. ...refState
  21. }
  22. }
  23. }
  24. </script>

F、watch监听多个值

以数组的形式监听多个值

6、多个根节点

  1. <template>
  2. <div>hello</div>
  3. <div>world</div>
  4. </template>