Vue3知识点
1.双向数据绑定
掌握实现双向数据绑定的方式
1.1实现表单双向数据绑定
什么是双向数据绑定呢?
双向数据绑定指的是数据和视图,双向数据绑是数据和视图绑定,数据变化同步视图,视图要是更改了数据,就要同步给数据源
那么如何实现双向绑定?
<template>
<input type="text" v-model="firstName" />
<button @click="onClickHandler">
button点击我
</button>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const firstName = ref("女魔头");
const onClickHandler = () => {
firstName.value = "亚瑟"
}
return { firstName, onClickHandler}
}
}
</script>
这样看不清楚,就可以用@update:modelValue = "onFirstNameChanged($event)"来监听双向数据绑定中数据的变化
<template>
<input
type="text"
v-model="firstName"
@update:modelValue="onFirstNameChanged($event)"
/>
</template>
<script>
import {ref} from "vue";
const firstName = ref("周杰伦")
const onFirstNameChanged = (event) => {
console.log(event)
}
return { firstName, onFirstNameChanged }
</script>
1.2实现组件双向数据绑定
我会分为三个版本来进行写入,最终版是友好版本
1.2.1普通版本
App.vue
<template>
<Test :Name="Name" @onNameChanged="onNaneChanged($event)"></Test>
</template>
<script>
import {ref} from "vue";
export default {
components: { Test },
name:"App",
setup() {
const Name = ref("EVA");
const onNameChanged = (event) => {
Name.value = event;
}
return { Name, onNameChanged }
}
}
</script>
Test.vue
<template>
<div>
{{Name}}
</div>
<button @click="changedName">
点击修改App.vue里面的数据
</button>
</template>
<script>
export default {
props:["Name"] //接收过来的数据
setup(props,{emit}) {
const changedName = () => {
emit("onNameChanged","⚙️战机")
}
}
}
</script>
1.2.2 升级版
App.vue
<template>
<Test v-model="Name"></Test>
<button @click="onClickHandler">
我是App组件中的button
</button>
</template>
<script>
import Test from "./componetns/Test.vue"
export default {
components:{Test},
name:"App",
setup() {
const Name = ref("EVA")
const onClickHandler = () => {
Name.vue = "战斗机甲"
}
return { firstName, onClickHandler }
}
}
</script>
Test.vue
<template>
<div>
{{modelValue}}
<button @click="onClickHandler">
我是Test组件中的button
</button>
</div>
</template>
<script>
export default {
props:["modelValue"],
setup(props,{ emit }) {
const onClickHandler = () => {
emit("update:modelValue",机甲小宝)
}
return { onClickHandler };
}
}
</script>
1.2.3究极版
App.vue
<template>
<Test v-model:firstname="firstname" v-model:lastname="lastname"></Test>
<button @click="onClickHandler">
我是App组件中的button
</button>
</template>
<script>
import Test from "./components/Test.vue";
export default {
components: { Test },
name:"App",
setup() {
const firstName = ref("张三");
const lastName = ref("李四");
const onClickHandler = () => {
firstName.value = "王五";
lastName.value = "宝强"
};
return { firstName,lastName,onClickHandler }
}
}
</script>
Test.vue
<template>
<div>
{{firstName}} {{lastName}}
<button @click="onClickHandler">
我是Test组件中的button
</button>
</div>
</template>
<script>
export default {
props:["firstName","lastName"]
setup(props, { emit }) {
const onClickHandler = () => {
emit("update:firstName","刘备")
emit("update:lastName","诸葛亮")
};
return { onClickHandler };
}
}
</script>
2.customRef
2.1复习防抖
防抖:监听用户的连续操作,最终只响应连续操作中的最后一次操作.
<template>
<button @click="onClickHandler">
button
</button>
</template>
<script>
export default {
name:"App",
setup() {
const onClickHandler = debounce(() => {
console.log("onClickHandler")
},400)
return { onClickHandler }
}
}
function debounce(handler,delay) {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(() => {
handler.call(this,arguments)
},dalay)
}
}
</script>
2.2customRef
创建具有自定义行为的响应式数据,通过拦截响应式的读取和设置实现。
需求:创建具有防抖功能的响应式数据.监听对响应式数据的连续更改,最后只响应最后一次更改
<template>
<input type="text" v-model="keyword" />
{{keyword}}
</template>
<script>
import { customRef } from "vue";
export default {
name:"App",
setup() {
const keyword = useDebounce("hello",400)
return { keyword }
}
}
function useDebounce(initialValue,delay) {
let timer = null
return customRef((track,trigger)) => {
return {
get() {
//跟踪initialValue值的变量
track();
return initialValue
},
set(newValue) {
clearTimeout(timer);
timer = setTimeout(() => {
initialValue = newValue;
//触发视图更新
trigger()
},delay)
}
}
}
}
</script>
3. setup语法🍬
npm init vue@3
<script setup></script>是一种编译时语法糖,用于在单文件组件中使用组合式API,如果你同时使用单文件组件和组合式API,建议使用该语法
它与普通语法相比,代码更加简洁,性能更加强悍,更好的TS 支持。
<script setup>
const msg = "hello Vue3 setup";
function log() {
console.log(msg)
}
</script>
<template>
<div @click="log">
{{msg}}
</div>
</template>
[解释] 以上代码就是会被编译成为setup函数代码,也就是说此处代码会在组件每次创建实时执行,在内部声明的顶级变量和函数都可以在模版中
<script setup>
//导入提前写好的函数,随便什么都可以处理数据
import { capitalize } from "./helps";
const msg = "hello vue3 setup";
</script>
<template>
{{capitalize(msg)}}
</template>
<script setup>
import { ref } from "vue";
const count = ref(0); // count 不需要跟之前在setup里面一样返回return { count },可以直接在模版中使用
</script>
<template>
<div @click="count++">
{{count}}
</div>
</template>
组件导入时不需要手动注册组件
<script setup>
import HelloWorld from "@/components/HelloWorld"
</script>
<template>
<HelloWorld />
</template>
如果父组件给子组件传递参数可以用defineProps接收参数并在模版上直接使用
//父组件
<script setup>
import HelloWorld from "./components/HelloWorld"
</script>
<template>
<HelloWorld msg="hello new setup" />
</template>
//子组件
<script setup>
//定义该组件接收的Props
//defineProps 在此处可以直接使用无需导入
defineProps({msg : String})
</script>
<template> {{ msg }} </template>
如果子组件要触发父组件自定义函数请看以下例子
<script setup>
import HelloWorld from "./components/HelloWorld"
function onDeleteHandler() {
alert("delete")
}
</script>
<template>
<HelloWorld @delete="onDeleteHandler"></HelloWorld>
</template>
<script setup>
//defineEmits在此处可以直接使用无需导入
defineEmits(["delete"])
</script>
<template>
<button @click="$emit('delete')">
delete button
</button>
</template>
如果子组件要暴露数据可以根据以下代码来学习
<script setup>
const count = 0;
//定义当前组件向外暴露的数据
defineExpose({ count })
</script>
<script setup>
import HelloWorld from "./components/HelloWorld";
import { ref } from "vue";
const instance = ref(null);
function log() {
console.log(instance.value.count);
}
</script>
<template>
<HelloWorld ref="instance"></HelloWorld>
<button @click="log">
button
</button>
</template>
如果在setup里面异步请求操作呢?
<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>