之前零零散散的用vue3写一些案例,一直也没有做过任何总结,这段时间忙里偷闲写点东西吧。

vue3新语法统一写在 <script setup lang="ts">,这种组合式API写法跟vue2完全不一样【vue2采用option api】。

1.ref =》基本数据类型响应

   定义的数据需要使用value去获取值

const iptValue = ref('html')
const list = ref(['css', 'js'])
console.log(iptValue.value, list.value)
// html Proxy {0: 'css', 1: 'js'}

2.reactive =>定义对象

const iptValue = ref('html')
const list = reactive(['css', 'js'])
console.log(iptValue.value, list)

const addIput = () => {
  console.log('addIput')
  list.push(iptValue.value)
  iptValue.value = ''
  console.log(iptValue.value, list)
}

<template>
  <a-input v-model:value="iptValue"></a-input>
  <a-button type="primary" @click="addIput">添加</a-button>
</template>

3.组件传值方式

  • props ===》 defineProps 父组件传值给子组件,获取组件传值

<template>
  <h1>{{ msg }}</h1>
  <ul>
     <li v-for="(item, index) in labels" :key="index">{{ item }}</li>
   </ul>
</template>

<script setup lang="ts">
import { defineProps } from 'vue'
defineProps<{
  //1 采用ts专有声明,无默认值
  msg: string
  labels?: string[]
}>()
//2 采用ts专有声明,有默认值
interface Props {
  msg?: string
  labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

defineProps({ //3 非ts专有声明
  msg: String,
  num: {
    type:Number,
    default: ''
  }
})
</script>

<style scoped lang="less">
</style>

  • emit ===》 defineEmits 子组件向父组件事件传递

<template>
 <a-button @click="clickThis">子传父添加事件方法</a-button>
</template>

<script setup lang="ts">
 /*ts专有*/
const emit = defineEmits<{
  (e: 'editValue', iptValue: string): void
}>()
/*非ts专有*/
const emit = defineEmits(['editValue'])
const clickThis = () => {
  emit('editValue', '子传父输入框值')
}
</script>

<style scoped lang="less">
</style>

  • defineExpose 组件暴露自己的属性

可以通过ref拿到组件实例,进而获取组件中的属性值

//子组件
<template>
  <h1>{{ msg }}</h1>
  <a-button @click="clickThis">子传父添加事件方法</a-button>
  <div>
    <ul>
      <li v-for="(item, index) in labels" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { ref, defineProps, defineEmits, defineExpose } from 'vue'
// defineProps<{
//   //1 采用ts专有声明,无默认值
//   msg: string
//   labels?: string[]
// }>()
//2 采用ts专有声明,有默认值
interface Props {
  msg?: string
  labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})
/*ts专有*/
const emit = defineEmits<{
  (e: 'editValue', iptValue: string): void
}>()
/*非ts专有*/
// const emit = defineEmits(['editValue'])
const clickThis = () => {
  console.log('clickThis')
  emit('editValue', '子传父输入框值')
}

// defineProps({ //3 非ts专有声明
//   msg: String,
//   num: {
//     type:Number,
//     default: ''
//   }
// })

const childValue = ref('childValue123')
defineExpose({ childValue })

</script>

<style scoped lang="less">
</style>

 父组件

<script setup lang="ts">
import { ref, reactive } from 'vue'
import ChildConp from './components/ChildConp.vue'

const iptValue = ref('html')
const list = reactive(['css', 'js'])
console.log(iptValue.value, list)
// 在 Vue 2.x 中用实例上的 $refs 属性获取模版元素中 ref 属性标记 DOM 或组件信息,在这里用 ref() 包装对象也可以用来引用页面元素和组件;
const childConp = ref(null) //拿到子组件实例
const addIput = () => {
  console.log('addIput')
  list.push(iptValue.value)
  iptValue.value = ''
  console.log(iptValue.value, list)
  console.log('childValue', childConp.value.childValue) //childValue childValue123
}
const editValue = (value) => {
  iptValue.value = value
}
</script>

<template>
  <ChildConp ref="childConp" msg="vue3 prop" :labels="list" @editValue="editValue"></ChildConp>
  <a-input v-model:value="iptValue"></a-input>
  <a-button type="primary" @click="addIput">添加</a-button>
</template>

<style>
</style>
  • v-model  实现双向绑定

<ChildComponent v-model:title="pageTitle" />
语法糖==》
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
  • refs ===》 ref 拿到组件实例

  • provide/inject

<template>
  <!-- 子组件 -->
  <child-components></child-components>
  <!-- 父组件 -->
  <div class="child-wrap input-group">
    <input
      v-model="value"
      type="text"
      class="form-control"
      placeholder="请输入"
    />
    <div class="input-group-append">
      <button @click="handleAdd" class="btn btn-primary" type="button">
        添加
      </button>
    </div>
  </div>
</template>
<script setup>
import { ref, provide } from 'vue'
import ChildComponents from './child.vue'
const list = ref(['JavaScript', 'HTML', 'CSS'])
const value = ref('')
// 向子组件提供数据
provide('list', list.value)
// add 触发后的事件处理函数
const handleAdd = () => {
  list.value.push(value.value)
  value.value = ''
}
</script>

 子组件

<template>
  <ul class="parent list-group">
    <li class="list-group-item" v-for="i in list" :key="i">{{ i }}</li>
  </ul>
</template>
<script setup>
import { inject } from 'vue'
// 接受父组件提供的数据
const list = inject('list')
</script>
  • eventBus ===》Vue官方推荐mitt[2]或tiny-emitter[3];

  • vuex/pinia(状态管理工具)

单文件组件 <script setup> | Vue.js (vuejs.org)

有道云笔记

总结了Vue3的七种组件通信方式,别再说不会组件通信了 (qq.com)

「1.9W字总结」一份通俗易懂的 TS 教程,入门 + 实战! (qq.com)

Logo

前往低代码交流专区

更多推荐