赞
踩
- <script lang="ts" setup name="App">
- <style scoped>
define开头的函数是可以不用引入的哦
目标1:实现一个加法
- <template>
- <p>这是一个数字{{ number }}</p>
- <button @click="Add">我是加法</button> //绑函数
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue" //引入响应包
- let number = ref(0); //数据响应化
- function Add(){
- number.value++; //必须改数据的值
- }
- </script>
目标1:实现一个对象修改
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { reactive } from "vue" //引入响应包
- let number = reactive({name:"苹果",price:100}); //数据响应化
- function Add(){
- number.price = number.price + 10;
- }
- </script>
目标1:实现一个对象修改
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- let number = ref({name:"苹果",price:100});
- function Add(){
- number.value.price = number.value.price + 10;
- }
- </script>
ref > reactive ------- ref._value == reactive
宏观角度看:
1.ref 用来定义:--> 基本类型数据 , 对象类型数据
2.reactive用来定义:--> 对象类型数据
区别:
1.ref创建的变量必须使用.value
2.reactive重新分配一个新对象,会失去响应式
使用原则:
1.若需要一个基本类型的响应式数据,必须使用ref
2.若需要一个响应式对象,层级不深,ref,reactive都可以
3.若需要一个响应式对象,且层级较深,推荐使用reactive
ref
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- <button @click="Switch">我是切换</button>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- let number = ref({name:"苹果",price:100});
-
- function Add(){
- number.value.price = number.value.price + 10;
- }
- function Switch(){
- number.value = {name:"梨" , price: 200}
- }
- </script>
reactive
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- <button @click="Switch">我是切换</button>
- </template>
-
- <script setup lang="ts">
- import { reactive } from "vue"
- let number = reactive({name:"苹果",price:100});
-
- function Add(){
- number.price = number.price + 10;
- }
- function Switch(){
- //number = {name:"梨" , price: 200} //错误写法
- //number = reactive({name:"梨" , price: 200}) //错误写法
- Object.assign(number,{name:"梨" , price: 200})
- }
-
- </script>
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第一阶段了
——————————————————————————————————————
toRefs与reactive的比对 , ref好像不需要
- Proxy(Object) {name: '苹果', price: 100} //reactive的内值并没有响应化
- {name: ObjectRefImpl, price: ObjectRefImpl} //toRefs会使内值响应化
所以,我们现在有一个要解决的问题
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { reactive } from "vue"
- let number = reactive({
- name:"苹果",
- price:100
- });
-
- let {price} = number;
-
- function Add(){
- price += 1 //为什么数据没有发生变化
- }
-
- </script>
目标1:使内数据响应化
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { reactive , toRefs } from "vue"
- let number = reactive({
- name:"苹果",
- price:100
- });
-
- let {price} = toRefs(number); //内数据ref化 ,注:此处为地址引用,
- //修改的为实际number
- function Add(){
- price.value += 1 //所以这里要加value
- }
-
- </script>
目标1:使内数据某一个值响应化
- <template>
- <p>我是{{ number.name }} , 我值{{ number.price }}元</p>
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { reactive , toRef } from "vue"
- let number = reactive({
- name:"苹果",
- price:100
- });
-
- let price = toRef(number , "price")
-
- function Add(){
- price.value += 1
- }
-
- </script>
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第二阶段了
——————————————————————————————————————
打断一下,这里教大家一下数据的双向绑定v-model
- <template>
- 姓:<input type="text" v-model="firstName"><br>
- 名:<input type="text" v-model="lastName"><br>
- 姓名:{{ firstName + lastName }}
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
-
- let firstName = ref("博丽")
- let lastName = ref("七七")
- </script>
当数据更改时 input.value赋值给firstName导致姓名发生变化,lastName同理
目标1:不想让全名等于firstName+lastName
- <template>
- 姓:<input type="text" v-model="firstName"><br>
- 名:<input type="text" v-model="lastName"><br>
- 姓名:{{ fullName }}
- </template>
-
- <script setup lang="ts">
- import { ref , computed } from "vue"
-
- let firstName = ref("博丽")
- let lastName = ref("七七")
- let fullName = computed(()=>{
- return firstName.value + lastName.value;
- })
- </script>
但是,我们又出现了新的问题,computed绑定的fullName是可读的,我们修改不了它的值,fullName.value = ”1“ 这会报错的,那我们应该怎么优化呢?
- <template>
- 姓:<input type="text" v-model="firstName"><br>
- 名:<input type="text" v-model="lastName"><br>
- 姓名:{{ fullName }}
- </template>
-
- <script setup lang="ts">
- import { ref , computed} from "vue"
-
- let firstName = ref("博丽")
- let lastName = ref("七七")
- let fullName = computed({
- get(){
- return firstName.value + lastName.value
- },
- set(val){ val就是传入的fullName.value
- console.log(val)
- firstName.value = val
- .... //这里我们就可以进行后续操作啦
- }
- })
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第三阶段了
——————————————————————————————————————
作用:监视数据的变化
特点:Vue3中的watch只能监视以下四种数据
1.ref定义的数据
2.reactive定义的数据
3.函数返回一个值
4.一个包含上述内容的数组
注:watch里ref不写value哦
目标1:加到10后停止输出
- <template>
- 我是数字{{ number }}
- <button @click="Add">我是加法</button>
- </template>
-
- <script setup lang="ts">
- import { ref, watch } from "vue"
-
- let number = ref(0);
- function Add() {
- number.value++;
- }
- const stopWatch = watch(number, (newValue, oldValue) => {
- console.log(newValue , oldValue);
- if(newValue > 10){
- stopWatch() //大于10就结束监视
- }
- })
- </script>
若修改的是ref定义的对象中的属性,newValue和oldValue都是新值,因为它们是同一个对象
若修改整个ref定义的对象,newValue是新值,oldValue是旧值,因为不是同一个对象了
目标1:深度监视
- <template>
- 我是名字:{{ number.name }}<br>
- 我是价格:{{ number.price }}<br>
- <button @click="Add">我是加法</button>
- <button @click="Switch">我是切换</button>
- </template>
-
- <script setup lang="ts">
- import { ref, watch } from "vue"
-
- let number = ref({name:"博丽七七" , price:100});
- function Add() {
- number.value.price++;
- }
- function Switch(){
- number.value = {name:"李四" , price:300}
- }
- watch(number, (newValue, oldValue) => {
- console.log(newValue , oldValue);
- } , {deep:true})//深度监视可选
- </script>
此时,有个注意点深度监视开启时,如果价格改变,新旧值则是相同的
- Proxy(Object) {name: '博丽七七', price: 101}
- Proxy(Object) {name: '博丽七七', price: 101}
- Proxy(Object) {name: '博丽七七', price: 101}
- Proxy(Object) {name: '博丽七七', price: 101}
如果改变对象,新旧值则是
- Proxy(Object) {name: '李四', price: 300}
- Proxy(Object) {name: '博丽七七', price: 102}
一般我们不管旧值
监视reactive定义的对象类型数据,默认开启了深度监视,且无法关闭
同上
- <template>
- 我是名字:{{ number.name }}<br>
- 我是价格:{{ number.price }}<br>
- <button @click="Add">我是加法</button>
- <button @click="Switch">我是切换</button>
- </template>
-
- <script setup lang="ts">
- import { reactive, watch } from "vue"
-
- let number = reactive({name:"博丽七七" , price:100});
- function Add() {
- number.price++;
- }
- function Switch(){
- Object.assign(number,{name:"李四" , price:300})
- }
- watch(number, (newValue, oldValue) => {
- console.log(newValue , oldValue);
- })
- </script>
若该属性值不是对象类型,需要写成函数形式
若该属性值依然是对象类型,可直接写,也可写成函数,建议直接写成函数
同上
- <template>
- 我是名字:{{ number.name }}<br>
- 我是价格:{{ number.price }}<br>
- <button @click="Add">我是加法</button>
- <button @click="Switch">我是切换</button>
- </template>
-
- <script setup lang="ts">
- import { reactive, watch } from "vue"
-
- let number = reactive({
- name: "博丽七七",
- price: 100,
- other: {
- a: 1,
- b: 2,
- }
- });
- function Add() {
- number.price++;
- number.other.a++;
- }
- function Switch() {
- Object.assign(number, { name: "李四", price: 300 })
- }
- watch(() => number.price, (newValue, oldValue) => {
- console.log(newValue, oldValue);
- })
- //这里只展示推荐写法
- watch(() => number.other, (newValue, oldValue) => {
- console.log(newValue, oldValue);
- }, { deep: true })
- </script>
同上
- watch([() => number.other , number.price , ......], (newValue, oldValue) => {
- console.log(newValue, oldValue);
- }, { deep: true })
- watch([temp , heigth], (Value) => {
- let [newTemp , newHeigt] = value
- 传入不同变化,是会赋给两个哦
- })
watch与watchEffect对比
1.都能监听响应式数据的变化,不同的是监听数据变化的方式不同
2.watch:要明确指出监视的数据
3.watchEffect:不用明确指出监视的数据
目标1:实现一个水位控制器
- <template>
- 需求:当水温达到60度,或水位达到80cm<br>
- 当前水温:{{ temp }}<br>
- 当前水位:{{ height }}<br>
- <button @click="tempAdd">增加水温</button><br>
- <button @click="heightAdd">增加水位</button><br>
- </template>
-
- <script setup lang="ts">
- import { ref, watchEffect } from "vue"
-
- let temp = ref(10);
- let height = ref(0);
-
- function tempAdd() {
- temp.value += 10;
- }
- function heightAdd() {
- height.value += 10;
- }
- watchEffect(()=>{
- if(temp.value >=60 || height.value >=80){
- console.log("发出警告")
- }
- })
- </script>
-
- <style></style>
与之相对的watch写法
- watch([temp , height],(value)=>{
- let [newTemp , newHeight] = value
- if(newTemp >= 60 || newHeight >= 80){
- console.log("发出警告")
- }
- })
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第四阶段了
——————————————————————————————————————
这里是轻松愉快小课堂
父组件
- <template>
- <Test ref="abc"></Test> //ref命名
- <button @click="add">点我</button>
- </template>
-
- <script setup lang="ts">
- import Test from "./components/test.vue"
- import { ref } from "vue";
- let abc = ref() //ref获取
- function add() {
- console.log(abc.value.a) //获取子组件的值
- }
- </script>
子组件
- <template></template>
- <script setup lang="ts">
- import { ref, defineExpose } from "vue";
- let a = ref("你好");
- let b = ref(1);
- defineExpose({ a, b }) //注意:必须要暴露出去父组件才可以拿的到哦
- </script>
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第五阶段了
——————————————————————————————————————
How to write an interface document about typescript
my typescript file
- export interface PersonInter {
- id:string,
- name:string,
- age:number
- price?:number //这是可选的
- } //这是给对象用的
- export type Persons = Array<PersonInter , ... , ...>//这是给数组用的
- export type Persons = PersonInter[]//这么写也写
use file
- <script ... ... >
- import {type PersonInter , type Persons} from "ts路径"//记得要写type哦
- let personList:Persons = [{},{},{}]
- let personList = reactive<Persons>([{},{},{}])//优雅写法
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第六阶段了...呃,应该叫ts第一阶段
——————————————————————————————————————
这节涉及到组件通信,非常重要哦,一定要好好听
入门
父组件
<子组件 a = "abc"></子组件> //父组件往子组件传了个值
子组件
- <template>
- {{ a }}
- </template>
- <script ... ... >
- import { defineProps } from "vue"
- defineProps(["a"]) //获得父组件传入的值
- //注意,defineProps是有返回值的,返回值为对象
- const jkl = defineProps(["a"])//打印的话是一个对象哦
- </script>
基础props (限制类型)
defineProps<{list:Persons}>() //同ts , ()里面没东西
进阶props (限制类型+限制必要性+指定默认值)
- import { withDefaults } from "vue"
- withDefaults(defineProps<{list?:Persons}>(),{
- list:()=> [{id:... , name:... , ......}]
- })
- <Test person="ppa" ></Test>
-
- withDefaults(defineProps<{person?: string}>(),{
- person: "bbc"
- })
——————————————————————————————————————
这么难的props居然都被你学会了,继续加油吧,第七阶段, complete!
——————————————————————————————————————
这个不难,直接按流程走一遍就行
- import { ref , onBeforeMount , onMounted ,
- onBeforeUpdate , onUpdated ,
- onBeforeUnmount , onUnmounted} from "vue"
- let sum = ref(0) //数据
- function add(){} //方法
- console.log() //创建
- onBeforeMount(()=>{}) //挂载前
- onMounted(()=>{}) //挂载完毕 出生
- onBeforeUpdate(()=>{}) //数据更新前
- onUpdated(()=>{}) //数据更新完毕 常用
- onBeforeUnmount(()=>{}) //卸载前 例如v-if不满足的时候
- onUnmounted(()=>{}) //卸载完毕 常用
子优先于父
——————————————————————————————————————
第八阶段结束了,进入第九阶段Ciallo~(∠・ω< )⌒★
——————————————————————————————————————
简单axios , 记得下载axios
- import { ref , reactive } from "vue"
- import axios from "axios"
- export default function (){
- let doglist = reactive([...])
- async function getDog(){
- try{
- let result = await axios.get()
- dogList.push(result.data.message)
- } catch(error){
- alert(error)
- }
- }
- //向外部提供东西
- return {dogList , getDog}
- }
什么是hook
进入src目录,创建hook文件,里面就放常调用的函数
使用
- import useDog from "@/hook/useDog"
- const {dogList,getDog} = useDog()
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第九阶段了
——————————————————————————————————————
安装vue-router src文件夹里创建router文件夹
创建一个ts文件
- import { createRouter, createWebHistory } from "vue-router"
- //引入一个一个可能要呈现的组件
- import abc from "@/components/test.vue"
-
- //创建路由
- const router = createRouter({
- history: createWebHistory(),
- routes: [
- {
- path:"/home",
- component:abc
- }
- ]
- })
-
- export default router
main.ts里引入router , 使用router
父组件
- <RouterLink to="路由path" active-class="激活时的类名"></RouterLink>
- //略等于a标签 , active-class路由自带的
- to的第二种写法--> :to="{path:"/about"}"
-
- <RouterView></RouterView> //路由展示区
- <script......>
- import { RouterView , RouterLink } from "vue-router"
- </script>
src创建pages或views放路由页
换路由会被视作生命周期(卸载)
定义
- routes: [
- {
- name:"abc"
- path:"/home",
- component:abc
- }
- ]
使用
<RouterLink :to="{name:'abc'}" active-class="激活时的类名"></RouterLink>
定义
- routes: [
- {
- name:"abc"
- path:"/home",
- component:abc,
- children:[
- {
- path:"detail" //子集就不用写/了
- component:...
- }
- ]
- }
- ]
使用 , 别忘了路由插槽
<RouterLink to="/news/detail"></RouterLink>
太简单了,直接上代码
父组件
- <RouterLink
- :to="{
- path:"/fff/fff",
- query:{
- id:news.id,...
- title:news.title...
- }
- }"></RouterLink>
- //等同于....?fff=...&kkk=...
路由页获取
- {{ query.id }}
- <script>
- import { toRefs } from "vue"
- import { useRoute } from "vue-router"
- let route = useRoute()
- let { query } = toRefs(route)
- </script>
太简单了,直接上代码
路由规则 , 记得占位
- routes: [
- {
- name:"abc"
- path:"/home",
- component:abc,
- children:[
- {
- name:"//"
- path:"detail/:id/:title?" //子集就不用写/了
- //?为可选
- component:...
- }
- ]
- }
- ]
父组件
RouterLink 不能用path换路由了
- <RouterLink
- :to="{
- name:"avcs",
- params:{
- id:news.id,...
- title:news.title...
- }
- }"></RouterLink>
- //等同于/.../.../...
子组件用params就行
第一种写法 (将路由收到的params参数作为props传给路由组件)
- children:[
- {
- name:"//"
- path:"detail/:id/:title?" //子集就不用写/了
- //?为可选
- component:...
- props:true
- }
- ]
使用
- {{ id }}
- defineProps(["id"])
第二种写法 (query传)
- children:[
- {
- name:"//"
- path:"detail/:id/:title?" //子集就不用写/了
- //?为可选
- component:...
- props(route){
- return route.query
- }
- }
- ]
用法同上
第三种写法 (随便传)
- children:[
- {
- name:"//"
- path:"detail/:id/:title?" //子集就不用写/了
- //?为可选
- component:...
- props:{
- a:100,
- b:200
- }
- }
- ]
<RouterLink replace :to="{name:'abc'}"></RouterLink>
编程式路由导航(脱离RouterLink进行路由跳转)
例:
- import { useRouter } from "vue-router"
- const router = useRouter()
- router.push("路由地址")
正确写法
- const router = useRouter()
-
- interface NewsInter {
- id:string,
- number:number
- }
-
- function ...(news:NewInter){
- router.push({ //push换replace的话就不能返回上一步了 , 看需求
- name:"/"
- query:{
- id:news.id
- number:news.number
- }
- })
- }
- path:"原路径"
- redirect:"新路由路径" -> 会执行这个地址
——————————————————————————————————————
最长的路由你也都学会了吗,太棒啦,继续加油吧
——————————————————————————————————————
父传子
- <template>
- 父组件
- <Test :car="car"></Test>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- import Test from "./components/test.vue"
- let car = ref("奔驰");
- </script>
-
- <template>
- 子拿到的{{ car }}
- </template>
-
- <script setup lang="ts">
- defineProps(["car"])
- </script>
子传父
- <template>
- 父组件<br>
- 父拿到的{{ toy }}
- <Test :sendToy="getToy"></Test>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- import Test from "./components/test.vue"
- let toy = ref("")
-
- function getToy(value:string){
- toy.value = value
- }
- </script>
-
- <template>
- 子给的{{ toy }}
- <button @click="sendToy(toy)">子给父的</button>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- let toy = ref("玩具车");
- defineProps(["sendToy"])
- </script>
子传父
- <template>
- 父组件<br>
- 父拿到的{{ toy }}
- <Test @sendToy="getToy"></Test>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- import Test from "./components/test.vue"
-
- let toy = ref("")
-
- function getToy(value:string){
- toy.value = value
- }
-
- </script>
- ///
- <template>
- 子给的{{ toy }}
- <button @click="emit('sendToy' , toy)">子给父的</button>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- let toy = ref("玩具车");
- const emit = defineEmits(["sendToy"])
- </script>
记得下载 pnpm i mitt
首先,src的目录里新建utils文件夹里面新建一个emitter.ts的文件
- //引入mitt
- import mitt from "mitt"
- const emitter = mitt()
- export default emitter
使用
- <template>
- 父组件<br>
- 父有的{{ toy }}
- <Test></Test>
- <button @click="emitter.emit('send-toy' , toy)">父给子</button>
- </template>
-
- <script setup lang="ts">
- import { ref } from "vue"
- import Test from "./components/test.vue"
- import emitter from './utils/emitter';
-
- let toy = ref("玩具车")
-
- </script>
- /
- <template>
- 父给子的{{ toy }}
- </template>
-
- <script setup lang="ts">
- import { ref, onUnmounted } from "vue"
- import emitter from "../utils/emitter";
- let toy = ref("");
- emitter.on("send-toy", (value: string) => {
- toy.value = value
- })
- onUnmounted(() => {
- emitter.off("send-toy")
- })
- </script>
——————————————————————————————————————
恭喜你,学到这你已经学完了Vue3的第十一阶段了
——————————————————————————————————————
<slot></slot>
- 插得元素
- <template v-slot:插槽名>
- 被插的
- <slot name="插槽名"></slot>
插槽子传父
插得元素
- <template v-slot="params">
- <ul>
- <v-for="item in params.youxi":key="item.id"></v-for>
- </ul>
- </template>
被插的
- <slot :youxi="game"></slot>
- <script>
- let games = reactive([
- {},{},{}
- ])
- </script>
插的起名这么起
<template v-slot:插槽名="params">
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。