*与vue2的区别
vue2配置项的风格
vue3组合式的风格
*通过createApp创建实例
*setup早于beforecreate
1.创建vue3方式
1。vue-cli创建(基于webpack)
2。vite创建(官方推荐,安装node才可支持npm 安装后重启电脑)
2.ref和reactive
import { ref, reactive } from 'vue';
区别:
1.ref创建的变量必须使用.value (可以使用 volar 插件自动添加. value )。
2. reactive 重新分配一个新对象,会失去响应式(可以使用 Object . assign 去整体替换)。let game=reactive([ {id:'1',name:'game1'}, {id:'2',name:'game2'}, {id:'3',name:'game3'} ]) function changeGame(){ Object.assign(game,reactive([ {id:'1',name:'game5'}, {id:'2',name:'game6'}, {id:'3',name:'game7'} ])) }
使用原则:
1. 若需要一个基本类型的响应式数据必须使用 ref 。
2.若需要一个响应式对象,层级不深, ref 、 reactive 都可以。ref定义对象本质是借助reactive实现响应式的。3.若需要一个响应式对象,且层级较深,推荐使用 reactive 。
3.toRef和toRefs
- toRef: 复制 reactive 里的单个属性并转成 ref
- toRefs: 复制 reactive 里的所有属性并转成 ref
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制 info 里的 greet 属性
let rGreet = toRef(info, 'greet')
rGreet.value = 'world!'
rGreet 改变 则 info里面的greet改变
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制整个 info
let rInfo = toRefs(info)
// 更改 rInfo.greet
const onChangeGreet = () => {
rInfo.greet.value = 'world!'
}
4.computed 计算属性-有缓存,所计算结果发生变化才再次执行
方法用几次叫用几次,没有缓存
<template>
<div>
计算属性
<div><span>姓:</span> <input type="text" v-model="xing"></div>
<div><span>名:</span> <input type="text" v-model="ming"></div>
<div><span>全名:{{ funllname }}</span> </div>
<div><span>全名:{{ funllname }}</span> </div>
<div><span>全名:{{ funllname }}</span> </div>
<button @click="changename">改变姓名为li-si</button>
</div>
</template>
<script lang="ts" setup>
import { ref,computed } from 'vue';
let xing=ref("zhang")
let ming=ref("san")
// computed有缓存 多次调用没有改变的话只执行一次
// 这么定义的funllname是只读的
// let funllname=computed(()=>{
// return xing.value+"-"+ming.value
// })
// 这么定义才是funllname可读写的
let funllname=computed({ //funllname是个ref定义的响应式数据
get() {
return xing.value+"-"+ming.value
},
set(name){
console.log(name)
let [str1,str2]=name.split("-")
xing.value=str1
ming.value=str2
}
})
function changename(){
//funllname是个ref定义的响应式数据
funllname.value="li-si"
}
</script>
5.watch监听
情况一:监视ref定义的基本类型
<template> <div> 情况一:监视ref定义的基本类型 sumde:{{ sum }} <button @click="addsum">sum1+1</button> </div> </template> <script lang="ts"> export default { name:'watch' } </script> <script lang="ts" setup > import { ref,watch } from "vue"; let sum=ref(1) function addsum(){ sum.value =sum.value+1 } // 情况一:监视ref定义的基本类型 let stopWatch=watch(sum,(newvalue,oldvalue)=>{ console.log(newvalue,oldvalue) if(newvalue>=10){ stopWatch()//结束监视 } }) </script>
情况二.监听ref定义的对象类型数据
·若修改的是 ref 定义的对象中的属性, newValue 和 oldValue 都是新值,因为它们是同一个对象。(person.value.name+="~")
.若修改整个 ref 定义的对象, newValue 是新值, oldValue 是旧值,因为不是同一个对象了。( person.value={name:'张三222',age:118} //地址值发生了变化)<template> <div> 情况二:监视ref定义的对象类型 <p> 姓名:{{ person.name}}</p> <p> 年龄:{{person.age}}</p> <button @click="changename">改变姓名</button> <button @click="changeage">改变年龄</button> <button @click="changeperson">改变person</button> </div> </div> </template> <script lang="ts" setup > // 情况二:监视ref定义的对象类型 let person=ref({name:'张三',age:18}) function changename(){ person.value.name+="~" } function changeage(){ person.value.age+=1 } function changeperson(){ // person.value.name+="~" // person.value.age+=1 person.value={name:'张三222',age:118} //地址值发生了变化 } watch(person,(newvalue,oldvalue)=>{ // 此时监视的是地址值的变化(changeage(),changename()person无变化), // 若想监视对象内部属性的变化,要开启深度监视 console.log("person改变了",newvalue,oldvalue) }) watch(person,(newvalue,oldvalue)=>{ // 若想监视对象内部属性的变化,要开启深度监视 console.log("person改变了",newvalue,oldvalue) },{deep:true}) </script>
情况三:监视reactive定义的对象数据类型 地址值没有发生变化,所以newvalue和oldvalue值一样
监视reactive定义的对象类型:默认开启深度监视,隐式的创建一个深层的监听,且关不掉
<div> 情况三:监视reactive定义的对象类型 <p> 姓名:{{ person.name}}</p> <p> 年龄:{{person.age}}</p> <button @click="changename">改变姓名</button> <button @click="changeage">改变年龄</button> <button @click="changeperson">改变person</button> </div> // 情况三:监视reactive定义的对象类型 let person3=reactive({name:'张三',age:18}) function changename3(){ person3.name+="~" } function changeage3(){ person3.age+=1 } function changeperson3(){ Object.assign(person3,{name:'张三222',age:118})//把相同的属性值赋值给person3 } watch(person3,(newvalue,oldvalue)=>{ //三个方法person3都发生了改变 // 监视reactive定义的对象类型:默认开启深度监视,隐式的创建,且关不掉 console.log("person改变了",newvalue,oldvalue) })
*情况四
监视 ref 或 reactive 定义的【对象类型】数据中的某个属性,注意点如下:
1.若该属性值不是【对象类型】(如person4.age)且是基本类型,需要写成函数形式。
2.若该属性值是依然是【对象类型】,可直接写watch(()=>{ person4.car},(newvalue,oldvalue)=>{}(不完美),也可写成函数,不过建议写成函数(不完美)。结论:监视的要是对象里的属性,最好写函数式,若监视的是地址性的改变,最好手动都开启{deep:true}(ref或者reactive)
let person4=reactive({ name:"zhangsan", age:18, car:{ brand:"奥迪", peice:100 } }) watch(()=>{return person4.age},(newvalue,oldvalue)=>{ console.log("person改变了",newvalue,oldvalue) }) watch(()=>{return person4.car},(newvalue,oldvalue)=>{ console.log("person改变了",newvalue,oldvalue) },{deep:true})
*情况五
监视上述多种数据
let person4=reactive({ name:"zhangsan", age:18, car:{ brand:"奥迪", peice:100 } }) watch([()=>{return person4.age},()=>{return person4.name}],(newvalue,oldvalue)=>{ console.log("person改变了",newvalue,oldvalue) },{deep:true})
6.watchEffect
watch:要明确指出检测的数据;
watchEffect:不用明确指出检测的数据;
let temp=ref(20)
let hei=ref(30)
watchEffect(()=>{
if(temp.value>50||hei.value>80){
console.log("调用服务器")
}
})
7.标签的ref属性+子传父
用在普通的dom标签上,获取的是dom节点
用在组件标签上,获取的是组件实例对象
1.用在普通的dom标签上,获取的是dom节点
<template>
<div class="greetings">
<p>1111 </p>
<p ref="title">2222 </p>
<button @click="showtitle">出现ref的内容</button>
</div>
</template>
<script lang="ts" setup>
import {ref} from "vue"
// 用于存储ref标记的内容,名字和ref里面的名字一致
let title=ref()
function showtitle(){
console.log(title.value)
}
</script>
<style scoped>
</style>
2.用在组件标签上,获取的是组件实例对象
//父 <script lang="ts" setup> import person from './components/person.vue'; import {ref} from 'vue' let ren=ref() function showren(){ console.log(ren.value,ren.value.a,ren.value.b,ren.value.c) } </script> <template> <header> <div class="wrapper"> <button @click="showren">showren</button> <person ref="ren"/> </div> </header> </template> //子 <template> <div class="greetings"> </div> </template> <script lang="ts"> export default { name:'person' } </script> <script lang="ts" setup> import {ref,defineExpose} from "vue" let a=ref(1); let b=ref(2); let c=ref(3); defineExpose({a,b,c}) </script> <style scoped> </style>
8.defineProps父传子
父
<template> <header> <div class="wrapper"> <person4 a="哈哈" :listperson="person"/> </div> </header> </template> <script lang="ts" setup> import person4 from './components/person4.vue'; // @ts-ignore import {person} from '@src/type' import {ref,reactive} from 'vue' let person=reactive<person>([]) </script>
子
<template> <div class="greetings"> <ul> <li v-for="item in propsValue.listperson" :key="item.id"> {{ item.name }}--{{item.age}} </li> </ul> </div> </template> <script lang="ts"> export default { name:'person4' } </script> <script lang="ts" setup> import { defineProps ,withDefaults} from 'vue'; // @ts-ignore import { person } from '@src/type'; // 接受所有 // let propsValue=defineProps(["a","listperson"]) // 接收listperson + 限制类型 // let propsValue=defineProps<{listperson:person}>() // 接收listperson + 限制类型 + 限制必要性 + 指定默认值 //父级不传listperson,设置默认值 let propsValue=withDefaults(defineProps<{listperson?:person}>(),{ listperson:()=>[{id:'1',name:"默认",age:0}] }) </script>
9.生命周期
vue 2
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestory(不用的时候销毁 <person v-if="isshow"> isshow为false )
- destroyed
vue 3
除了这些函数 vue3 还增加了些生命周期,可以直接导入 onXXX 一族的函数来注册生命周期钩子:与 2.x 版本生命周期相对应的组合式 API。
1、beforeCreate -> 使用 setup()
2、created -> 使用 setup()
3、beforeMount -> onBeforeMount
4、mounted -> onMounted
5、beforeUpdate -> onBeforeUpdate
6、updated -> onUpdated
7、beforeDestroy -> onBeforeUnmount(卸载前)
8、destroyed -> onUnmounted
9、errorCaptured -> onErrorCaptured
创建 setup()
挂载 onBeforeMount onMounted
更新 onBeforeUpdate onUpdated
卸载 onBeforeUnmount onUnmounted