vue3 composition api

1,composition api的使用.vue

Setup函数是一个新的组件选项,作为组件中composition API的起点
从生命周期钩子的角度来看,setup会在beforeCreate钩子函数之前执行
Setup中不能使用this,this指向undefined

<template>
  <div>
    <h1>当前鼠标的位置</h1>
    <div>{{ msg }}</div>
    <div>{{ x }}, {{ y }}</div>
  </div>
</template>
<script>
import { reactive, onMounted, onUnmounted, toRefs, ref } from 'vue'
function mouseHandle() {
  const mouse = reactive({
    x: 0,
    y: 0
  })
  const move = (e) => {
    mouse.x = e.pageX
    mouse.y = e.pageY
  }
  onMounted(() => {
    document.addEventListener('mousemove', move)
  })
  onUnmounted(() => {
    document.removeEventListener('mousemove', move)
  })
  return mouse
}
export default {
  setup() {
    // composition api的入口  setup会在beforeCreate钩子函数之前执行 
    // 不能访问this
    const mouse = mouseHandle()
    const msg = ref('hello')
    return {
      ...toRefs(mouse),
      msg
    }
  }
}
</script>

2,reactive使用

Reactive函数接受一个普通对象,返回该对象的响应式代理。

<template>
  <div class="app">
    <div>{{ car.brand }}----{{ car.price }}</div>
    <button @click="car.brand = '奔驰'">修改</button>
  </div>
</template>
<script>
import { reactive } from 'vue'
export default {
  setup() {
    // 1. setup需要返回值, setup中返回的值才能在模板中使用
    // 2. reactive中传入一个普通对象,返回一个代理对象
    const car = reactive({
      brand: '宝马',
      price: 100
    })
    return {car}
  }
}
</script>

3,ref使用

ref函数接受一个简单类型的值,返回一个可改变的ref对象。返回的对象有唯一的属性 value
在setup函数中,通过ref对象的value属性可以访问到值
在模板中,ref属性会自动解套,不需要额外的.value
如果ref接受的是一个对象,会自动调用reactive

<template>
  <div class="app">
    <div>我的金钱:{{ money }}</div>
    <button @click="money++">修改</button>
  </div>
</template>
<script>
import {ref } from 'vue'
export default {
  setup() {
    // 1. ref函数接受一个简单类型, 返回一个响应式的对象
    // 2. 这个响应式对象只有一个属性 value
    // 3. 在模板中使用ref,会自动解套,,,,会自动调用value
    let money = ref(100)
    money.value++
    return {money}
  }
}
</script>

4,toRefs使用

把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref
Reactive的响应式功能是赋予给对象的,但是如果给对象解构或者展开的时候,会让数据丢失响应式的能力。
使用toRefs可以保证该对象展开的每一个 属性都是响应式的

<template>
  <div class="app">
    <div>我的金钱:{{ money }}</div>
    <div>{{ car.brand }} --- {{ car.price }}</div>
    <div>{{ name }}</div>
    <button @click="money++">修改</button>
    <button @click="name = 'ls'">修改</button>
  </div>
</template>
<script>
import { reactive, ref, toRefs } from 'vue'
export default {
  setup() {
    const state = reactive({
      money: 100,
      car: {
        brand: '宝马',
        price: 1000000
      },
      name: 'zs'
    })
    return {
      // money, car, name
      ...toRefs(state)
    }
  }
}
</script>

5,readonly

传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理。
一个只读的代理是“深层的”,对象内部任何嵌套的属性也都是只读的。
可以防止对象被修改

<template>
  <div class="app">
    <div>我的钱: {{ money }}</div>
    <div>{{ car.brand }} ---{{ car.price }}</div>
    <button @click="money++">按钮</button>
    <button @click="car.price = 200">按钮</button>
  </div>
</template>
<script>
import { reactive, ref, readonly } from 'vue'
export default {
  setup() {
    const money = ref(100)
    const car = readonly({
      brand: 'zs',
      price: 18
    })
    return {
      money: readonly(money),
      car
    }
  }
}
</script>

6,computed

Computed函数用于创建一个计算属性
如果传入的是一个getter函数,会返回一个不允许修改的计算属性
如果传入的是一个带有getter和setter函数的对象,会返回一个允许修改的计算属性

<template>
  <div class="app">
    <div>我今年的年龄:<input type="text" v-model="age" /></div>
    <div>我明年的年龄:<input type="text" v-model="nextAge" /></div>
    <div>我后年的年龄: <input type="text" v-model="nextAge2" /></div>
  </div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
  setup() {
    // computed计算属性的使用
    const age = ref(18)
    // computed是一个函数
    // 1. 传入一个函数 getter 返回一个不允许修改的计算属性。
    const nextAge = computed(() => {
      return parseInt(age.value) + 1
    })
    // 2. 传入一个对象,包括get和set,,可以创建一个可以修改的计算属性
    const nextAge2 = computed({
      get() {
        return parseInt(age.value) + 2
      },
      set(value) {
        age.value = value - 2
      }
    })
    return {  
      age,nextAge,nextAge2
    }
  }
}
</script>

7, watch

Watch函数接受3个参数。
参数1:数据源,可以是ref或者getter函数
参数2:回调函数
参数3:额外选项,immediate和deep
Watch可以监听一个ref或者一个带有返回值的getter函数
Watch可以监听单个数据源,也可以监听多个数据源
watch函数会有返回值,用于停止监听。

<template>
  <div class="app">
    <div>{{ money }}</div>
    <div>{{ car.brand }}</div>
    <button @click="money++">按钮</button>
    <button @click="car.brand = '奔驰'">按钮2</button>
  </div>
</template>
<script>
import { ref, toRefs, watch, reactive } from 'vue'
export default {
  setup() {
    const state = reactive({
      money: 100,
      car: {brand: '宝马'}
    })
    // 接受3个参数
    // 参数1:监视的数据源 可以是一个ref 或者是一个函数
    // 参数2:回调函数 (value, oldValue) =>{}
    // 参数3:额外的配置 是一个对象 {  deep: true, immediate: true } //深度监听,初次渲染就立即执行
    // watch(
    //   () => state.money,
    //   (value, oldValue) => {
    //     console.log('money变化了', value, oldValue)
    //   }
    // )

    // watch(
    //   () => state.car,
    //   (value) => {
    //     console.log('车变了', value)
    //   },
    //   {
    //     deep: true,
    //     immediate: false
    //   }
    // )
    // watch([() => state.money, () => state.car], ([money, car]) => {
    //   console.log('数据变化了', money, car)
    // })

    watch(
      state,  //监听整个数据
      (value) => {console.log('数据变化了', value)},
      {deep: true }
    )

    // watch用于实现监听
    return {...toRefs(state)}
  }
}
</script>

8,生命周期钩子函数

Vue3提供的生命周期钩子注册函数只能在 setup() 期间同步使用

9,provide和inject

Vue3中提供了provide和inject提供依赖注入,用于实现组件之间的通讯。类似于vue2中的provide和inject。
Vue3提供的provide和inject可以用于跨多级组件进行通讯

<template>
  <div class="app">
    <h1>钩子函数----{{ money }}</h1>
    <button @click="money++">按钮</button>
    <hr />
    <Demo :money="money"></Demo>
  </div>
</template>
<script>
import Demo from './Demo.vue'
import { ref, provide } from 'vue'
export default {
  components: {
    Demo
  },
  setup() {
    // provider和inject
    const money = ref(100)
    // js中作用域问题
    const changeMoney = (n) => {
      console.log(money)
      money.value = n
    }
    // 组件提供了money属性
    provide('money', money)  //传值 
    provide('changeMoney', changeMoney)  //子传父,传方法
    return {
      money
    }
  }
}
</script>

子组件

<template>
  <div class="demo">
    我是demo组件 ---{{ money }}
    <hr />
    <Hello></Hello>
  </div>
</template>
<script>
import { inject } from 'vue'
import Hello from './Hello.vue'
export default {
  components: {
    Hello
  },
  setup(props) {   //使用props方法,没有了this
    console.log(props)  
    const money = inject('money')  //多个属性,就要inject多次
    return {
      money
    }
  },
  props: {
    money: Number
  }
}
</script>

子孙组件

<template>
<div>
  hello组件 ---{{ money }}
  <button @click="fn">修改</button>
</div>
</template>
<script>
import { inject } from 'vue'
export default {
  setup() {
    const money = inject('money')
    const changeMoney = inject('changeMoney')
    const fn = () => {
      changeMoney(200000)  //调用传值
    }
    return {
      money,
      fn
    }
  }
}
</script>

10,模板refs

为了获得对模板内元素或组件实例的引用,我们可以像往常一样在 setup() 中声明一个 ref 并返回它

<template>
  <div class="app">
    <h1 ref="hRef">钩子函数----123</h1>
    <Demo ref="dRef"></Demo>
  </div>
</template>
<script>
import Demo from './Demo.vue'
import { ref, provide, onMounted } from 'vue'
export default {
  components: {Demo},
  setup() {
    // 创建了一个空的ref
    const hRef = ref(null)
    const dRef = ref(null)
    onMounted(() => {
      console.log(hRef.value.innerHTML)
      console.log(dRef.value)
    })
    return {hRef,dRef}
  }
}
</script>
原文地址:https://www.cnblogs.com/xm0328/p/14268602.html