初使用

和Vue2使用的optionsAPI(例如: 数据放 data 中, 方法放 methods中)不同的是, Vue3是用了composition API, 提升了代码的可读性和可维护性, 同时也保留了Vue2的optionsAPI.

<template>
  <div>当前点击次数:{{ count }}</div>
  <button @click="add">点击</button>
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from 'vue'

export default defineComponent({
  setup() {
    const count = ref(0)
    const add = () => {
      count.value++
    }

    return {
      count,
      add,
    }
  },
})
</script>

  • composition api的使用, 需要配置一个setup 函数
  1. setup 函数是一个新的组件选项, 作为组件中 compositionAPI 的起点
  2. 从生命周期角度来看, setup 会在beforeCreate 钩子函数之前执行
  3. setup 中不能使用 this, this 指向 undefined 在模版中需要使用的数据和函数,需要在 setup 返回。

  • ref 和 reactive 的最佳使用方式:
  1. 明确的对象,明确的属性,用 reactive,其他用 ref
  2. 从vue3.2之后,官方更推荐使用 ref

script setup

但是defineComponent和setup这种写法有点累赘, 所以现在官方推荐使用setup模板。 script setup是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 script 语法更加简洁

<template>
  <div>当前点击次数:{{ count }}</div>
  <button @click="add">点击</button>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
const add = () => {
  count.value++
}
</script>

script setup 优势:

  1. 使用 ts 项目不需要再 defineComponent 包裹了。
  2. 无需再 return 了, template 可直接使用,顶层的绑定会自动暴露给模板。

计算属性computed函数

在Vue3中 computed为函数, 写法有两种, 且可以使用多次

<template>
  <div>原本的值 <input type="text" v-model.number="num" /></div>
  <div>改变后的值 {{ nextNum }}</div>
  <div>相互影响的值 <input type="text" v-model.number="revNum" /></div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
const num= ref(10)
// 不带set的计算属性
const nextNum = computed(() => {
  return num.value + 1
})

// 带set的计算属性
const revNum= computed({
  get() {
    return num.value + 2
  },
  set(val: number) {
    num.value = val - 2
  },
})
</script>

侦听器watch函数

watch 侦听器, 接收三个参数

  1. 参数1: 监视的数据源, 可传入多个监听值, 以数组格式传入
  2. 参数2: 回调函数
  3. 参数3: 额外的配置
// 监听单个ref
const num = ref(100)
watch(num, (value, oldValue) => {
  console.log(value)
})

// 监听多个ref
const num1 = ref(100)
const num2 = ref(0)
watch([num1, num2], (value) => {
  console.log(value)
})

// 监听ref复杂数据
const user = ref({
  name: 'name',
  age: 18,
})
watch(
  user,
  (value) => {
    console.log('user变化了', value)
  },
  {
    // 深度监听,当ref的值是一个复杂数据类型,需要深度监听
    // 但是如果是以reactive创建的复杂类型数据,则不需要
    deep: true,
    immediate: true
  }
)

组件通讯

父传子 (script setup中子组件引入后可以使用)
父组件中给子组件传值与Vue2相同故省略, 主要不同在子组件获取父组件的值, 不再使用props, 而需要使用defineProps

// 父组件给子组件传入两个值
<script setup lang="ts">
import { computed } from 'vue'

// 规定传递数据的类型
interface Props {
  age: number
  name: string
}

// defineProps: 接收父组件传递的数据
const props = defineProps<Props>()

// 使用
const addAge = computed(() => {
  return props.age ++
})
</script>

<template>
  <h3>子组件---{{ addAge }} --- {{ name }}</h3>
</template>

子传父

  1. 子组件通过 defineEmits 获取emit对象(因为没有this)
  2. 子组件通过emit触发事件,并且传递数据
  3. 父组件提供方法
  4. 父组件通过自定义事件的方式给子组件注册事件,与Vue2相同,定义一个方法函数去接收值
// 子组件 
const rValue = ref('give back')
// 定义回传的方法 defineEmits
const emit = defineEmits(['giveBack'])

const giveBack = () => {
	emit('giveBack', rValue)
}

跨层级通讯-依赖注入 - provide 和 inject

  1. 父组件利用 provide 提供数据(数值与方法函数都可提供)
//父组件
import { provide, ref } from 'vue'
const num = ref(100)
// provide提供给子组件 key和value不需要相同
provide('num', num)
  1. 子组件利用inject来接收
<script setup lang="ts">
import { inject, Ref } from 'vue'

// inject来插入来自父组件的值
const getNum = inject<Ref<number>>('num')

const changeNum = (m: number) => {
   getNum && getNum.value ++
}
</script>
<template>
  <h5>子组件--{{ getNum }}</h5>
  <button @click="changeNum">修改</button>
</template>
  • 注意: 如果用defineProps来通讯, 子组件必须用defineEmit来父组件接收来改变父组件的值,因为prop的值是readonly。而通过provide/inject的值,子组件可以直接修改,但也可以通过provide一个方法给子组件修改。

模板中 ref 的使用

在标签中使用 ref="xxx"来记录取的哪个元素
在script中,通过赋值来取得值,但是赋值的命名必须与标签中的命名一致

<div ref="divRef">通过Ref拿我</div>
<button @click="changeRefHTML>点我改变</button>

//script
const divRef = ref<HTMLDivElement | null>(null)
const changeRefHTML = () => {
  if (divRef.value) {
    divRef.value.innerHTML = '变了'
  }
}

通过ref获取子组件的值/方法

//父组件中使用子组件
<Form ref="formRef" />
<button @click="changeSon">点我改变</button>
// 获取子组件
import Form from "./components/Form.vue"

// typeof获取类型 Instancetype 泛型类型
const formRef = ref<InstanceType<typeof Form> | null>(null)

const changeSon = () => {
  if (refForm.value) {
	// 子组件里面的方法/取值方法类似
    refForm.value.refMethod()
  }
}
Logo

前往低代码交流专区

更多推荐