组件化
SFC组件
常规sfc写法
<template>
<h1>{{ titleInfo.color }}</h1>
<div>
{{ $store.state.counter }}
</div>
<div>
{{ doubleCounter }}
</div>
<div v-for="item in todos" :key="item.id">
{{ item.name }}
</div>
<input
type="text"
v-model="todoName"
@keydown.enter="addTodo(newTodo(todoName))"
/>
</template>
<script lang="ts">
import { defineComponent, PropType, ref } from "vue";
import { TitleInfo, Todo } from "../types";
const ConstPropType= {
titleInfo: {
type: Object as PropType<TitleInfo>, // 使用PropType<T>定义类型类型校验才能生效
required: true,
},
} as const // 断言为const才能放入props中
export default defineComponent({
props: ConstPropType,
data() {
return {
// counter: 1,
// counter: this.s,
todos: [] as Todo[],
todoName: "",
};
},
computed: {
doubleCounter(): number {
return this.$store.state.counter * 2;
},
},
created() {
this.todos.push({
id: 123,
name: "vue3",
completed: false,
});
},
methods:{
newTodo(todoName:string):Todo{
return {
id:12344325,
name:todoName,
completed:false
}
},
addTodo(todo:Todo):void{
this.todos.push(todo)
this.todoName=''
}
},
// setup(){
// const counter=ref(1)
// return {counter}
// }
});
</script>
<style scoped>
</style>
2.setup写法
<template>
<h1>{{ titleInfo.color }}</h1>
<div @click="$store.commit('add')">
{{ counter }}
</div>
<div>
{{ doubleCounter }}
</div>
<div v-for="item in todos" :key="item.id">
{{ item.name }}
</div>
</template>
<script lang="ts" setup>
// 此处标记为setup写法
// setup函数没有this
// 则script中的所有变量可以直接在template模板中使用
// 在script标签内需要读取value属性
import { defineComponent, ref,computed, reactive,defineProps } from "vue";
import type {PropType} from 'vue'
import { TitleInfo, Todo } from "../types";
import {useStore} from 'vuex'
import { key } from "../store";
const store=useStore(key)
console.log(store);
const counter=computed(():number=>store.state.counter)
//使用defineProps定义props
defineProps({
titleInfo: {
type: Object as PropType<TitleInfo>,
required: true,
},
})
const doubleCounter=computed(():number=>counter.value*2)
// const todos=ref([] as Todo[])
const todos=computed(()=>store.state.todos?.todos_c)
</script>
<style scoped>
</style>
jsx写法
import { defineComponent, PropType } from 'vue'
const PropType = {
msg: String,
age: {
type: Number as PropType<number>,
required: true,
},
} as const
export default defineComponent({
props: PropType,
setup(props) {
return () => {
return (
<div>
<div>Hello World{props.age}</div>
</div>
)
}
},
})
vue3迁移指南
vue3的setup函数
vue3 的 composition api
常见官方文档面试题
如何注册局部组件和全局组件
如何侦听一个深度嵌套的响应式对象
创建一个应用实例
reactive与ref区别
1、 从定义数据方面:
ref通常用来定义基本类型数据
reactive用来定义:对象(或者数组)类型数据
ref也可以用来定义对象或者数组类型的数据,内部会通过reactive转为代理对象
2、从原理方面:
ref通过Object.defineProperty()的get和set实现数据代理。
reactive使用Proxy实现数据代理,并且通过Reflect操作源对象内部的数据。
3、从使用方面:
ref操作数据需要.value,template模板中不需要。
reactive都不需要,value
vue3组件自定义事件
vue3中组件发送的自定义事件需要定义在emits选项中 emits.vue
<template>
<div @click="$emit('my-click')"></div>
</template>
<script>
export default {
// 这里一定要注册,不然会触发两次,原生的点击事件也会触发
emits: ['my-click']
}
</script>
helloworld.vue
<template>
<div>
<emits @my-click="onclick"></emits>
</div>
</template>
<script>
import emits form './emits.vue'
export default {
methods:{
onclick(){
console.log('自定义事件触发')
}
}
}
</script>
vue3.x 语法糖 defineEmits defineExpose父子组件传参 以及 调用方法
defineExpose
defineExpose可以将方法主动暴露出来
父组件
//通过ref
<tree :show="show"
ref="treeRef">
</tree>
// ref
const treeRef = ref()
const handleClick = () => {
//获取ref中的子组件方法handleNodeClick()
treeRef.value.handleNodeClick()
}
子组件
import { ref defineExpose } from 'vue'
const handleNodeClick = () => {
console.log('要执行的方法')
}
//将方法暴露出
defineExpose({ handleNodeClick})
defineEmits
父组件
//getGatewayData要获取的参数
<tree :show="show"
@gatewayData="getGatewayData">
</tree>
//执行方法获取参数
const getGatewayData = (e) => {
console.log('getGatewayData', e)
}
子组件
import { ref, defineEmits } from 'vue'
const emits = defineEmits(['handleNodeClick'])
const handleNodeClick = (e) => {
emits('gatewayData', label.value)
}