2022年5月25日 第二部分Vue3学习笔记
计算属性和监视
<template>
<H2>计算属性和监视</H2>
<fieldset>
<legend>姓名操作</legend>
姓氏:<input type="text" placeholder="请输入姓氏" v-model="user.firstName"><br>
名字:<input type="text" placeholder="请输入名字" v-model="user.lastName">
</fieldset>
<fieldset>
<legend>计算属性和监视</legend>
姓名:<input type="text" placeholder="显示姓名" v-model="fullName1" />
姓名:<input type="text" placeholder="显示姓名" v-model="fullName2">
姓名:<input type="text" placeholder="显示姓名" v-model="fullName3">
</fieldset>
</template>
<script lang="ts">
import {computed, defineComponent, reactive, ref, watch, watchEffect} from "vue";
export default defineComponent({
name: "App",
setup(){
// 定义一个响应式的对象
const user = reactive({
firstName:'我爱',
lastName:'学习'
})
// 通过计算属性的方式,实现第一个姓名的显示
// 计算属性的函数中如果只传入一个回调函数,表示get
// 返回的是一个Ref类型的对象
const fullName1 = computed(()=>{
return user.firstName+'_'+user.lastName
})
// 第2个输入框
const fullName2 = computed({
get(){
return user.firstName + '_' + user.lastName
},
set(val: string){
const names = val.split('_')
user.firstName = names[0]
user.lastName = names[1]
} ,
})
// 第三个输入框
const fullName3 = ref('')
watch(user,({firstName,lastName})=>{
fullName3.value = firstName + '_' + lastName
},{immediate:true,deep:true})
// immediate 默认会执行一次watch,deep 深度监视
// 也是监视,不需要配置immediate,本身默认就会进行监视
watchEffect(()=>{
const names = fullName3.value.split('')
user.firstName = names[0]
user.lastName = names[1]
})
// watch---可以监视多个数据,当监视非响应式数据的时候代码应使用如下回调的写法
watch([()=>user.firstName,()=>user.lastName],()=>{
console.log();
})
return{
user,
fullName1,
fullName2,
fullName3
}
}
})
</script>
生命周期函数
在2.x生命周期函数前面加on变为组合API
<template>
<h3>子级组件</h3>
<h3>{{msg}}</h3>
<button @click="update">更新数据</button>
</template>
<script>
import {defineComponent,ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default defineComponent({
name:'Child',
// vue2的钩子
beforeCreate(){
console.log('2中的beforeCreate');
},
created(){
console.log('2中的Create');
},
beforeMount(){
console.log('2中的beforemounted');
},
mounted(){
console.log('2中的mounted');
},
beforeUpdate(){
console.log('2中的beforeUpdate');
},
updated(){
console.log('2中的updated');
},
beforeDestroy() {
console.log('2中的beforeDestroy');
},
destroyed() {
console.log('2中的destroyed');
},
setup() {
console.log('3中的setup');
// 响应式的数据
const msg = ref('abc')
// 按钮点击事件的回调
const update = () => {
msg.value += '==='
}
onBeforeMount(()=>{
console.log('3中的onBeforeMount');
})
onMounted(()=>{
console.log('3中的onMounted');
})
onBeforeUpdate(()=>{
console.log('3中的onMounted');
})
onUpdated(()=>{
console.log('3中的onUpdated');
})
onBeforeUnmount(()=>{
console.log('3中的onBeforeUnmount');
})
onUnmounted(()=>{
console.log('3中的onUnmounted');
})
return {
msg,
update,
}
}
})
</script>
<style>
</style>
自定义hook函数
- 使用Vue3的组合API封装的可复用的功能函数
<template>
<h2>自定义hook函数</h2>
<h2>x:{{x}},y:{{y}}</h2>
</template>
<script lang="ts">
import { defineComponent,ref} from "vue";
import useMousePosition from './hooks/useMousePosition'
export default defineComponent({
name: "App",
setup(){
const { x , y } = useMousePosition()
return{
x,
y
}
},
})
</script>
====================================================
hook文件夹中的ts文件
import { onBeforeUnmount, onMounted, ref} from 'vue'
export default function() {
const x = ref(-1)
const y = ref(-1)
// 点击事件的回调函数
const clickHandler =(event:MouseEvent) =>{
x.value = event.pageX
y.value = event.pageY
}
// 页面已经加载完毕了,再进行点击操作
// 页面加载完毕的生命周期组合API
onMounted(()=>{
window.addEventListener('click',clickHandler)
})
// 组件卸载前的生命周期组合API
onBeforeUnmount(()=>{
window.removeEventListener('click',clickHandler)
})
return {
x,
y
}
}
=============分装ajax请求==================
<template>
<h2>自定义hook函数</h2>
<h2>x:{{x}},y:{{y}}</h2>
<h3 v-if="loading">正在加载中...</h3>
<H3 v-else-if="errorMsg">错误信息{{errorMsg}}</H3>
<ul v-else>
<li>id:{{data.id}}</li>
<li>address:{{data.address}}</li>
<li>distance:{{data.distance}}</li>
</ul> <hr>
<!-- 数组数据 -->
<ul v-for="item in data" :key="item.id">
<li>id:{{item.id}}</li>
<li>title:{{item.title}}</li>
<li>price:{{item.price}}</li>
</ul>
</template>
<script lang="ts">
import { defineComponent,ref,watch} from "vue";
import useMousePosition from './hooks/useMousePosition'
import useRequest from "./hooks/useRequest";
// 定义接口,约束对象类型
interface AddressData{
id:number,
address:string,
distance:string
}
interface ProductsData{
id:string,
title:string,
price:number
}
export default defineComponent({
name: "App",
setup(){
const { x , y } = useMousePosition()
// 发送请求
//const {loading,data,errorMsg} = useRequest<AddressData>('/data/address.json') // 获取对象数据
const{loading,data,errorMsg} = useRequest<ProductsData[]>('/data/products.json') // 获取数组数据
// 监视
watch(data,()=>{
if(data.value){
console.log(data.value.length)}
})
return{
x,
y,
loading,
data,
errorMsg,
}
},
})
toRefs
toRefs可以把一个响应式对象转换为普通对象,该普通对象的每个 property 都是一个 ref
应用:当从合成函数返回响应式对象时,toRefs非常有用,这样销毁组件就可以在不丢失响应式的情况下对返回的对象进行分解使用
<template>
<h2>toRefs的使用</h2>
<!-- <h3>name:{{state.name}}</h3>
<h3>age:{{state.age}}</h3> -->
<h3>name:{{name}}</h3>
<h3>age:{{age}}</h3>
</template>
<script lang="ts">
import { defineComponent,reactive,ref,toRefs,watch} from "vue";
export default defineComponent({
name: "App",
setup(){
const state = reactive({
name:'自来也',
age:47
})
// toRefs可以把一个响应式对象转换为普通对象,该普通对象的每个 property 都是一个 ref
// const state2 = toRefs(state)
const {name,age} = toRefs(state)
// 定时器,更新数据
setInterval(()=>{
// state2.name.value+='==='
// state.name+= "=="
name.value += '==='
},1000)
return {
// state, // 不是响应式的数据了
//...state2 // toRefs返回的对象
name,
age
}
}
})
ref的另一个作用
获取组件标签元素
<template>
<h2>ref的另一个作用:可以获取页面中的元素</h2>
<input type="text" ref="inputRef" />
</template>
<script lang="ts">
import {onMounted, defineComponent,reactive,ref,toRefs,watch} from "vue";
export default defineComponent({
name: "App",
// 当页面加载完毕后,文本框自动获取焦点
setup(){
// 默认是空的,页面加载完毕,说明组件已经存在了,获取文本框元素
const inputRef = ref<HTMLElement | null>(null)
// 页面加载后的生命周期API
onMounted(()=>{
inputRef.value&&inputRef.value.focus() // 自动获取焦点
})
return{
inputRef,
}
}
})
</script>
shallowRezctive与shallowRef
- shallowRezctive:只处理对象内最外层属性的响应式(浅层响应式)
- shallowRef: 只处理value的响应式,不进行对象的reactive处理
<template>
<h3>m1:{{m1}}</h3>
<h3>m2:{{m2}}</h3>
<h3>m3:{{m3}}</h3>
<h3>m4:{{m4}}</h3>
<hr>
<button @click="update">更新数据</button>
</template>
<script lang="ts">
import {onMounted, defineComponent,reactive,ref,toRefs,watch, shallowReactive,shallowRef} from "vue";
export default defineComponent({
name: "App",
setup(){
// 深度劫持
const m1 = reactive({
name:'鸣人',
age:20,
wife:{
name:'雏田',
munei:'ouki'
}
})
const m2 = shallowReactive({ name:'鸣人',
age:20,
wife:{
name:'雏田',
munei:'ouki'
}})
const m3 = ref({ name:'鸣人',
age:20,
wife:{
name:'雏田',
munei:'ouki'
}
})
const m4 = shallowRef({ name:'鸣人',
age:20,
wife:{
name:'雏田',
munei:'ouki'
}
})
const update = ()=>{
// 更新m1的数据 reactive
m1.wife.name += '=='
// 更新m2的数据 shallowReactive
//我懒得写了
// 更新m3的数据
// 更新m4的数据
}
return {
m1,
m2,
m3,
m4,
}
}
// 当页面加载完毕后,文本框自动获取焦点
})
</script>
先到这里吧...我有点受不了
要去补一下ajax,axios,还有js 完事直接项目
算了再坚持坚持
readonly和shallowReadonly
不行了 开摆