既然使用了vue3,那就使用最新的语法规则
setup
setup是组合式API的基础用法
注意:在setup()中不能用this
基础介绍(老语法)
<script>
export default {
props: {
title: {
type: String,
default:()=>{return '测试信息'}
}
},
setup(props, context) {
// Attribute (非响应式对象)
console.log(context.attrs)
// 插槽 (非响应式对象)
console.log(context.slots)
// 触发事件 (方法)
console.log(context.emit)
}
}
</script>
setup语法糖(高级语法)
<script setup lang="ts"><script>是在单文件组件(SFC)中使用组合式API的编译时的语法糖。相比普通的语法,它具有更多优势:
- 更少的样板内容,更简洁的代码,比如:省略了组件的注册声明,对象暴露return,methods,。
- 能够使用纯 Typescript 声明 props 和发出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
1、在setup语法糖中导入组件不需要注册声明,直接在视图中使用即可;
2、vue文件默认结构发生改变,js默认放到页面顶部,而视图template放到js下面,style放到页面底部;可以根据自己的喜好更改
3、导入vue文件必须写上文件后缀名.vue, 否则ts无法识别vue文件。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</template>
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
const props = defineProps({
title: {
type: String,
default:()=>{return '测试信息'}
}
})
console.log(props.title);
</script>
ref
ref是一个函数,用于定义处理基本数据类型,也可以定义应用类型数据
使用ref定义的数据,如果是基础类型数据,会转化为引用类型数据,可以实现响应式
- 在模板里使用ref直接使用变量名
- 在script里使用需要 变量名.value
```javascript
{{name}}
{{job.type}}
<a name="BjVUK"></a>
# reactive
- 作用:定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
- 语法:const代理对象reactive(源对象)接收一个对象(或数组),返回一个代理对象(proxy对象)
- reactive定义的响应式数据是“深层次的”。
- 内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作。
使用reactive定义的数据不需要使用value
```javascript
//引入
import { reactive } from 'vue';
let job = reactive({
type:"前端开发",
salary:"20K"
})
let job = reactive([1,2,3,4])
job.salary = "100k"
console.log(job,job.type)
//使用解构,会失去响应式
let {age,sex} = reactive({
age:"18",
sex:"男"
})
//此时修改age,sex页面上的age和sex不会更新
注意:reactive不能使用解构,否则不能实现响应式
- ref用来定义:基本类型数据。
- reactive用来定义:对象(或数组)类型数据。
- 备注:ref也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象。
- 从原理角度对比:
ref通过Object.defineProperty()的get与set来实现响应式(数据动持)
reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
- 从使用角度对比:
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value。
父组件传值给子组件 defineProps
vue2是使用props接收父组件的值
vue3使用的是defineProps**注意:defineProps** 和 **defineEmits** 都是只在 **<script setup>** 中才能使用的编译器宏
子组件在接收值之前不需要先引入 defineProps
//子组件
<template>
<h1> {{props.msg}}</h1>
<h1> {{props.age}}</h1>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const props = defineProps({
msg:{
type: String,
default: () => '默认值'
},
age:Number,
})
</script>
传递回调函数
不需要引入defineEmits,直接可以使用
defineEmits里面定义的是要传递的事件名称
//子组件
<template>
<button @click="handle">不欢迎</button>
</template>
<script setup lang="ts">
//要传递给父组件的事件on-change
const emit = defineEmits(['on-change'])
const handle =()=>{
emit('on-change', '传递成功了')
}
</script>
//父组件
<template>
<Child :msg="msg" @on-change="change"></Child>
</template>
<script setup lang="ts">
//使用之前先引入
import { ref,reactive,watchEffect } from 'vue';
import Child from './components/child.vue'
let msg=ref("欢迎光临")
const change=(value)=>{
console.log("父组件执行了",value)
}
</script>
计算属性 computed
使用之前先引入
<template>
<h2>{{message}}</h2>
<h2>{{message2("是一个中国人")}}</h2>
</template>
<script setup lang="ts">
//使用之前先引入
import { reactive,computed } from 'vue';
let person = reactive({
name:"oldUath",
age:"20岁"
})
let message = computed(()=>{
return person.name+'今年'+person.age
})
//传参的计算属性的写法
let message2=computed(()=>(aaa)=>{
return person.name+'今年'+person.age+aaa
})
</script>
watch监听
监听ref基本类型数据
可以正常监听ref定义的基本类型数据
<template>
<h2>{{sum}}-{{msg}}</h2>
<button @click="sum++,msg+='!'">点我+1</button>
</template>
<script setup lang="ts">
//使用之前先引入
import { ref,watch } from 'vue';
let sum = ref(0)
let msg = ref("你好")
//监视ref定义的数据
// watch(sum,(newValue,oldValue)=>{
// console.log("sum变化了",newValue,oldValue)
// })
//监视多个数据,把数据用数组包裹
watch([sum,msg],(newValue,oldValue)=>{
console.log("sum-msg变化了",newValue,oldValue)
//打印出来的也是两个数组
})
</script>
watch也可以传入第三个参数
//让watch立即执行,使用immediate
watch(sum,(newValue,oldValue)=>{
console.log("sum变化了",newValue,oldValue)
},{immediate:true})
监听reactive
监听reactive数据或者ref定义的引用对象数据时,无法获取到正确的oldVale
//让watch监听reactive
let person = reactive({
name:"你好呀",
age:18
})
watch(person,(newValue,oldValue)=>{
console.log("person",newValue,oldValue)
})
//让watch监听ref对象类型数据
let person1 = ref({
name:"你好呀",
age:18
})
//需要使用value
watch(person1.value,(newValue,oldValue)=>{
console.log("person",newValue,oldValue)
})
watchEffect
watchEffect和watch一样,都是监听,但是watchEffect只传一个函数,并且是用到了谁就监听谁
- watch的套路是:既要指明监视的属性,也要指明监视的回调。
- watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注亚的是过程(回调函数的函数体),所以不用写返回值。
```javascript
{{person}}
```

