织梦网站密码,扬中论坛网官网,网站排名易下拉效率,深圳网络优化推广公司创建第一个vue项目
1.安装node.js
cmd输入node查看是否安装成功 2.vscode开启一个终端#xff0c;配置淘宝镜像 # 修改为淘宝镜像源 npm config set registry https://registry.npmmirror.com
输入如下命令创建第一个Vue项目 3.下载依赖#xff0c;启动项目 访问5173端口 …创建第一个vue项目
1.安装node.js
cmd输入node查看是否安装成功 2.vscode开启一个终端配置淘宝镜像 # 修改为淘宝镜像源 npm config set registry https://registry.npmmirror.com
输入如下命令创建第一个Vue项目 3.下载依赖启动项目 访问5173端口 第一个Vue项目的目录结构 我们先打开main.ts这是我们vue工程的入口文件 在这里创建vue程序并把它挂载到id为app的标签下ps这里的App.vue是我们的根组件
再打开index.html 这里将main.js引入并挂载了app程序到这里。
最后打开App.vue也就是我们的根组件 先不看其他编码的细节我们可以大胆猜测HelloWorld.vue被挂到App.vue里面证实了它是根组件。
简单验证
Hello.vue
templateh1{{ msg }}/h1
/templatescript langts setuplet msgHello
/scriptstyle/style
App.vue
template
Hello/Hello
h1{{msg}}/h1
Hello/Hello
/templatescript langts setupimport Hello from ./components/Hello.vue;//引入Hello.vuelet msgApp
/scriptstyle
/style setup概述
setup语法糖
setup函数有一个语法糖可以让我们把setup函数从script里面独立出去
script setup langtsconsole.log(this) //undefined// 数据注意此时的name、age、tel都不是响应式数据let name 张三let age 18let tel 13888888888// 方法function changName(){name 李四//注意此时这么修改name页面是不变化的}function changAge(){console.log(age)age 1 //注意此时这么修改age页面是不变化的}function showTel(){alert(tel)}
/script
Vue的生命周期 setup函数会在beforeCreate函数前调用
响应式数据
基本类型的响应式数据
只能用ref
template
!-- altshifta 注释 --h1{{ msg }}/h1!-- 在template中不用age.value 会自动帮我们 .value --h1年龄{{ age }}/h1button clickf1点我年龄1/button
/templatescript langts setup nameHelloimport { ref } from vue;let msgHellolet ageref(18)//用ref包裹,让他成为响应式数据function f1(){age.value1 //在script中需要age.value才能得到它的值}
/script
在js中操作数据需要 .value 在模板中不需要
对象类型的响应式数据
可用reactive也可用ref
reactive
//对象类型的直接用reactive包起来即可let s1reactive({id:1,name:张三,age:28,sex:男,classroom:3})//取值不需要 .valuefunction changeS1Name(){s1.name张十三}
ref 仍需要 .value
由下图可知ref实现响应式对象的底层还是使用了reactive ref和reactive的区别
templateulli品牌:{{ car1.brand }}/lili价格:{{ car1.price }}/li/ulbutton clickf1ref改变/buttonbrulli品牌:{{ car2.brand }}/lili价格:{{ car2.price }}/li/ulbutton clickf2reactive改变1/buttonbutton clickf3reactive改变2/button
/templatescript langts setupimport { ref,reactive } from vue;//选中shift (let car1ref({brand:雪佛兰,price:666})let car2reactive({brand:奔驰,price:123})function f1(){car1.value{brand:宝马,price:987}}//可以function f2(){car2{brand:宝马,price:987}
/* car2.brandwda */ }//失效 无法获得Car的响应式对象要改整体只能成员属性一个个地改function f3(){Object.assign(car2,{brand:宝马,price:987})}//这样可以直接分配一个新对象给car2/script 解构响应式对象
如果我们要处理一个有很多成员的响应式对象且我们只希望对其中几个成员进行修改那么就可以对其进行解构
template
姓名h1{{name }}/h1
br
年龄h1{{ age }}/h1
br
性别h1{{ sex }}/h1
其他我们不想实时修改的属性h1{{ person.others }}/h1button clickchangeMsg修改/button
/templatescript langts setupimport { reactive,toRefs,toRef} from vue;let personreactive({name:张胜男,age:22,sex:女,others:其他属性...})//将解构出来的成员编程ref响应式对象let {name,age}toRefs(person)//解构多个let sextoRef(person,sex)//解构单个function changeMsg(){//因为解构出来的是ref对象所以要 .valuename.value李四;age.value99;sex.value男//此时页面可以变化console.log(name,age,sex);}/* let {name,age}personlet sexperson.sexfunction changeMsg(){name李四;age99;sex男// 李四99男// 但是页面上的姓名和年龄并没有改变// 这是因为解构出来的成员并不是响应式的console.log(name,age,sex);} *//script
计算属性
模板中的表达式虽然方便但也只能用来做简单的操作。如果在模板中写太多逻辑会让模板变得臃肿难以维护。因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。
它的格式如下
const 我们要计算的属性computed(function(){...return 计算结果})
案例
template
姓input v-modelxing
br
名input v-modelming
br
姓名span{{ name }}/span
/templatescript langts setupimport { computed,ref } from vue;let xingref(yang)let mingref(wei)let namecomputed(function (){return xing.value.slice(0,1).toUpperCase()xing.value.slice(1)-ming.value})/scriptstyle
span{border: 1px solid red;
}
/style
计算属性优于函数调用的地方在于它有缓存机制刷新页面时函数会重新计算计算属性检查调用的变量的值没有变动的话直接返回上次计算的结果。
此外计算属性的值是只读的 要对他实现可读可写要在computed函数里面提供get和set方法
template
姓input v-modelxing
br
名input v-modelming
br
姓名span{{ name }}/span
br
button clickchangeValue对计算属性的直接写操作会调用set方法,并且值会给到set方法的形参但是还是得通过更改调用的变量值才能复写/button
/templatescript langts setupimport { computed,ref } from vue;let xingref(yang)let mingref(wei)let namecomputed({get(){return xing.value.slice(0,1).toUpperCase()xing.value.slice(1)-ming.value},set(val){let[str1,str2]val.split(-)xing.valuestr1ming.valuestr2}})function changeValue(){name.valueLi-si}
/script
对计算属性的直接写操作会调用set方法,并且值会给到set方法的形参但是还是得通过更改调用的变量值才能复写 Vue常用指令 条件渲染 案例
!-- 条件渲染--
templatespan v-ifflagflag为true时显示这个span/spanbrspan v-showflag条件为真时渲染/spanbrspan v-ifsex1/spanspan v-else-ifsex0/spanspan v-else不男不女/spanbutton clickf1改变sex值/buttonbr/templatescript langts setupimport { ref } from vue;let flagtruelet sexref(0)function f1(){if(sex.value0){sex.value1return}else{sex.value0}}
/script
v-if和v-show的区别当判定条件为假时v-show只是不显示它所包裹的内容会保留它的结构而v-if时直接删除不保留
列表渲染 案例
!-- 列表渲染 --
templatetabletr v-forstu in students :keystu.idtd{{stu.id}}/tdtd{{stu.name}}/tdtd{{stu.age}}/tdtd v-ifstu.sex0/tdtd v-else/tdtd{{ stu.classroom }}/td/tr/table!-- v-for --span**************************/spandiv v-forvalue in myObjectspan{{ value }}/span/divspan**************************/spandiv v-for(stu, key) in students{{ key }}: {{ stu }}/divspan**************************/spandiv v-for(value, key, index) in myObject{{ index }}. {{ key }}: {{ value }}/div/templatescript langts setupimport { reactive } from vue;let studentsreactive([{id:2,name:李四,age:36,sex:1,classroom:2},{id:3,name:周天,age:77,sex:0,classroom:1},{id:4,name:王五,age:99,sex:0,classroom:8},{id:5,name:刘六,age:10,sex:1,classroom:5}])const myObject reactive({title: How to do lists in Vue,author: Jane Doe,publishedAt: 2016-04-10
})
watch
作用:监视数据的变化
牢记watch只能监视如下4种数据:
ref定义的数据。reactive定义的数据。函数返回一个值getter函数。一个包含上述内容的数组。
因为ref可以定义基本类型和对象类型所以watch对数据的监视可以分为5种情况
1.watch监视ref定义的基本类型数据
templatediv classpersonh1情况一监视ref定义的基本类型数据/h1h2当前求和为{{sum}}/h2button clickchangeSum点我sum1/button/div/templatescript langts setup import {ref,watch} from vue// 数据let sum ref(0)// 方法function changeSum(){sum.value 1}/*watch参数 要监视的数据 一个回调函数在被监视的数据的地址值发生改变时被调用 watch返回一个停止监视函数 调用它停止对watch的监视*/const stopwatch(sum,(newValue,oldValue){console.log(新值:newValue--旧值oldValue)if(newValue10){stop() //停止监视}})/script
重点回调函数在数据的地址值发生变化时被调用 2.watch监视ref定义的对象类型数据
templatediv classpersonh1情况二监视【ref】定义的【对象类型】数据/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangePerson修改整个人/button/div/templatescript langts setup namePersonimport {ref,watch} from vue// 数据let person ref({name:张三,age:18})// 方法function changeName(){person.value.name ~}function changeAge(){person.value.age 1}function changePerson(){person.value {name:李四,age:90}}/* 监视情况一监视【ref】定义的【对象类型】数据监视的是对象的地址值若想监视对象内部属性的变化需要手动开启深度监视watch的第一个参数是被监视的数据watch的第二个参数是监视的回调watch的第三个参数是配置对象deep、immediate等等..... */watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)},{deep:true})/script 可以看到开启深度监视后name和age字段的改变也会被我们监视到
****************************************
如果watch是这样写的(没有开启深度监视那么只有修改整个人回调函数才会被调用)
watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)})
3.watch监视reactive定义的对象类型数据
templateh2姓名:{{ student.name }}/h2h2年龄:{{ student.age }}/h2button clickf1改变姓名/buttonbutton clickf2改变年龄/buttonbutton clickf3改变整个人/button
/templatescript setupimport { reactive, watch } from vue;let studentreactive({name:张三,age:13})function f1(){student.namestudent.name~}function f2(){student.agestudent.age1}function f3(){Object.assign(student,{name:李四,age:99})}watch(student,(newValue,oldValue){console.log(发生变化,newValue,oldValue)})/*这样是不行的 因为reactive定义的整个对象会失去响应式function f3(){student{name:李四,age:99} }*/
/script 注意看这里的newValue和oldValue都是一样的
我们首先需要明确的是
1.回调函数只有被监视数据的地址发生改变时才被调用
2.reactive监视的数据默认开启深度监视也就是student里面的name和age会被监视到
以改变姓名举例watch监视到name地址值改变回调函数被调用但是我们监视的是student这个整体它的地址值未曾改变(Object.assign只是覆盖了两个字段的值)因此这时候拿到的newValue和oldValue都是修改后的值。
在实际开发中我们一般只用到修改后的值因此不需要太纠结。
watch(person,(value){console.log(我只要修改后的值,value)})
4.watch监视ref或reactive定义的对象类型里面的某个属性
reactive
templatediv classpersonh1情况四监视【ref】或【reactive】定义的【对象类型】数据中的某个属性/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2h2汽车{{ person.car.c1 }}、{{ person.car.c2 }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div/templatescript langts setupimport {reactive,watch} from vue// 数据let person reactive({name:张三,age:18,car:{c1:奔驰,c2:宝马}})// 方法function changeName(){person.name ~}function changeAge(){person.age 1}function changeC1(){person.car.c1 奥迪}function changeC2(){person.car.c2 大众}function changeCar(){person.car {c1:雅迪,c2:爱玛}}/script
如果要监视的是对象里面的一个基本数据类型要用getter方法
// 监视情况四监视响应式对象中的某个属性且该属性是基本类型的要写成函数式watch(() person.name,(newValue,oldValue){console.log(person.name变化了,newValue,oldValue)}) 如果监视的是对象里面的一个对象类型可以用getter方法也可以不用如果需要监视这个被监视的对象的里面还是要开启深度监视
// 监视情况四监视响应式对象中的某个属性且该属性是对象类型的可以直接写也能写函数更推荐写函数watch(()person.car,(newValue,oldValue){console.log(person.car变化了,newValue,oldValue)},{deep:true}) ref(同理reactive)
templatediv classpersonh1情况四监视【ref】或【reactive】定义的【对象类型】数据中的某个属性/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2h2汽车{{ person.car.c1 }}、{{ person.car.c2 }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div/templatescript langts setupimport {ref,watch} from vue// 数据let person ref({name:张三,age:18,car:{c1:奔驰,c2:宝马}})// 方法function changeName(){person.value.name~}function changeAge(){person.value.age 1}function changeC1(){person.value.car.c1 奥迪}function changeC2(){person.value.car.c2 大众}function changeCar(){person.value.car {c1:雅迪,c2:爱玛}}/script
如果要监视的是对象里面的一个基本数据类型要用getter方法
watch(()person.value.name,(newValue,oldValue){console.log(name改变了,newValue,oldValue)})
监视对象里面的一个对象类型开启深度监视
watch(()person.value.car,(newValue,oldValue){console.log(car改变了,newValue,oldValue)},{deep:true})
5.监视多个数据
统一用getter方法 然后开深度监视
templatediv classpersonh1情况五监视上述的多个数据/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2h2汽车{{ person.car.c1 }}、{{ person.car.c2 }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div/templatescript langts setup import {reactive,watch} from vue// 数据let person reactive({name:张三,age:18,car:{c1:奔驰,c2:宝马}})// 方法function changeName(){person.name ~}function changeAge(){person.age 1}function changeC1(){person.car.c1 奥迪}function changeC2(){person.car.c2 大众}function changeCar(){person.car {c1:雅迪,c2:爱玛} //因为这里是直接赋值 所以地址值改变了}// 监视情况五监视上述的多个数据watch(()[person.car,person.age],(newValue,oldValue){console.log(car或age被修改,newValue,oldValue)},{deep:true})/script watchEffect
官网立即运行一个函数相当于{immediate}同时响应式地追踪其依赖并在依赖更改时重新执行该函数。
说的通俗点就是watch的升级版直接写你的代码逻辑,他会根据你用到的去监听不需要你自己去告诉它你要监视哪些数据。
templatediv classpersonh1需求水温达到50℃或水位达到20cm则联系服务器/h1h2 iddemo水温{{temp}}/h2h2水位{{height}}/h2button clickchangePrice水温10/buttonbutton clickchangeSum水位10/button/div/templatescript langts setupimport {ref,watch,watchEffect} from vue// 数据let temp ref(0)let height ref(0)// 方法function changePrice(){temp.value 10}function changeSum(){height.value 10}/*// 用watch实现需要明确的指出要监视temp、heightwatch([temp,height],(value){// 从value中获取最新的temp值、height值const [newTemp,newHeight] value// 室温达到50℃或水位达到20cm立刻联系服务器if(newTemp 50 || newHeight 20){console.log(联系服务器)}})*/// 用watchEffect实现直接写你的代码逻辑,他会根据你用到的去监听//格式watchEffect( (){} )const stopWtach watchEffect((){// 室温达到50℃或水位达到20cm立刻联系服务器if(temp.value 50 || height.value 20){console.log(document.getElementById(demo)?.innerText)console.log(联系服务器)}// 水温达到100或水位达到50取消监视if(temp.value 100 || height.value 50){console.log(清理了)stopWtach()}})/script 标签的ref属性
用ref标记dom元素
取代了用id来标识标签因为用id来标识标签如果父组件和子组件中有id一样的会引起混淆。
用ref标记组件
子组件 向父亲暴露nameageclassroom非响应式 sex不暴露
父组件 得到子组件的实例测试按钮用于测试能否获取子组件的数据
测试 TS中的接口泛型 在src中新建一个和组件文件夹同级的types文件夹里面写ts文件
定义一个学生接口用于规范学生内的成员记得导出 使用接口规范数据格式 集合可用泛型 age 加上一个 ? 表示这个字段是可选的 没有age也不报错 reactive直接传泛型也可以
props的使用(父组件给子组件传数据)
第一种接收并保存到props里面
父组件 子组件 测试 第二种:接收限制类型
父组件
同上 如果父组件给出的数据和子组件要求的不一样会报错
子组件 测试
同上 第三种:
父组件 故意不传myList
子组件 怎么写第二种情况的语句 作为withDefaults的 第一个参数第二个参数用大括号包裹因为有多个不同类型的数据是对象起来里面 key: value 其中value要用返回值的形式给出这里用箭头函数
测试 Vue的生命周期
总述 测试Vue3的生命周期
父组件
!-- 父组件App.vue --
templateTestVueLifeCycle/TestVueLifeCycle
/templatescript langts setup nameAppimport TestVueLifeCycle from ./components/TestVueLifeCycle.vue;import { onBeforeMount,onMounted } from vue;onBeforeMount((){console.log(父-挂载前)})onMounted((){console.log(父-挂载完成)})/script
子组件
template
h2{{ count }}/h2
button clickf1点我count1/button
/templatescript langts setupimport { ref } from vue;import { onBeforeMount,onMounted } from vue;//挂载前挂载完成import { onBeforeUpdate,onUpdated } from vue;//更新前更新完成import { onBeforeUnmount,onUnmounted } from vue;//销毁前销毁完成let countref(0)function f1(){count.value}console.log(setup完成vue2中创建前创建完成工作)onBeforeMount((){console.log(子-挂载前)})onMounted((){console.log(子-挂载完成)})onBeforeUpdate((){console.log(更新前)})onUpdated(((){console.log(更新完成)}))onBeforeUnmount((){console.log(销毁前)})onUnmounted((){console.log(销毁完成)})
/script
测试 更新的钩子函数的执行不难理解(执行了两次按钮点击的效果)那前面的钩子为什么会这样执行呢
答
1.运行我们的vue工程首先来到index.html这是我们的入口html它调用了main.ts 2.来到main.ts这里调用了App.vue并尝试创建它并将它挂载到index.html的名为app的div标签下(输出 父-setup 父-挂载前) 3.来到App.vue 它自上而下执行所以会先执行所有孩子的创建和挂载工作等所有的孩子都创建和挂载完成后App.vue才执行onMounted函数 自定义hooks
准备工作首先导入axios的依赖 案例
首先写一个子组件如下
template
h2{{ sum }}/h2
button clickaddSum点我sum1/button
hrimg v-for(dog,index) in dogs :keyindex :srcdog.src
br
button clickaddDog点我狗狗1/button
/templatescript langts setupimport axios from axios;import { ref,reactive } from vue;let sumref(0)let dogsreactive([{src:https://images.dog.ceo/breeds/pembroke/n02113023_6826.jpg}])function addSum(){sum.value;}function addDog(){axios.get(https://dog.ceo/api/breed/pembroke/images/random).then(response{let msg{src:response.data.message}console.log(msg)dogs.push(msg)}).catch(error{console.log(error,找不到路径)})}/scriptstyle
img{height: 100px;margin-left: 5px;
}
/style
这个组件实现的效果如下有两个功能点击按钮sum1 点击按钮出现一张新的狗狗的图片 注意观察代码的结构如果一个组件要实现的功能多起来时方法和数据都放在一个vue里面会导致代码特别臃肿要同时找到一个方法所需要的数据和方法也十分困难这时候hook就派上用场了。
什么是hookhook有什么优势 什么是hook—— 本质是一个函数把setup函数中使用的Composition API进行了封装类似于vue2.x中的mixin。自定义hook的优势复用代码, 让setup中的逻辑更清楚易懂。
用自定义hook对上述代码进行改进
1.首先在src目录下新建一个hooks目录
2.编写自定义hook按功能分类将一个功能的方法和数据抽离出来用函数包裹最后把需要暴露的数据和方法交出去)
注意hook的命名规范为: useXxxxx
useSum.ts useDog.ts 3.在vue中调用hook
template
h2{{ sum }}/h2
button clickaddSum点我sum1/button
hrimg v-for(dog,index) in dogs :keyindex :srcdog.src
br
button clickaddDog点我狗狗1/button
/templatescript langts setup
/* 引入 */import useSum from ../hooks/useSum;import useDog from ../hooks/useDog;
/* 调用 */let {sum,addSum}useSum()let {dogs,addDog}useDog()
/scriptstyle
img{height: 100px;margin-left: 5px;
}
/style
十分清爽这里体现了vue3组合式api的思想 Vue中的路由
用路由器实现一个基本的切换效果
首先先安装路由器依赖 1.在src文件夹中创建一个router文件夹
2.准备好需要的vue们
这里准备了一个Main.vue作为主界面要在这里面切换CommunityFriendHome三个组件
2.写一个router
MyRouter.ts
import { createRouter,createWebHistory } from vue-router;
import community from ../components/Community.vue;
import friend from ../components/Friend.vue;
import home from ../components/Home.vue;const routercreateRouter({history:createWebHistory(),routes:[{path:/community,component:community},{path:/friend,component:friend},{path:/home,component:home}]})
3.在main.ts里面注册这个router
import { createApp } from vue;
import App from ./App.vue;//引入路由器
import router from ./router/MyRouter;const appcreateApp(App)app.use(router)//注册路由器app.mount(#app)
4.在主界面上用RouteLink组件绑定对路由路径的响应
Main.vue
!-- 登录成功后的主界面 --template
h2登录成功后的主界面/h2
div classapp!-- 导航区 --div classnavigateRouterLink to/community active-classactive classnavi-style社区/RouterLinkRouterLink to/friend active-classactive classnavi-style交友/RouterLinkRouterLink to/home active-classactive classnavi-style个人中心/RouterLink/div!-- 展示区 --div classmain-contentRouterView/RouterView/div/div/templatescript langts setupimport {RouterLink,RouterView} from vue-router /scriptstyle
.active{color: red;
}
.navi-style{margin-left: 10px;
}
/style
Community.vue(其他两个结构同这个一样)
!-- 社区模块 --
templateh2社区模块/h2/templatescript langts setup/scriptstyle/style
效果 两个注意点
1.路由组件通常存放在pages 或 views文件夹一般组件通常存放在components文件夹。ps路由组件就是通过路由器才能被渲染的组件也就是写在RouterLink里面的组件
2.通过点击导航视觉效果上“消失” 了的路由组件默认是被卸载掉的需要的时候再去挂载。
路由器工作模式
history模式 hash模式 怎么写要跳转的路由三种方法
to的两种写法
!-- 第一种to的字符串写法 --
router-link active-classactive to/home主页/router-link!-- 第二种to的对象写法 --
router-link active-classactive :to{path:/home}Home/router-link
命名路由后面可以用来简化路由跳转和传参的问题
在路由器中给路由规则命名 在Main.vue中这样写
可以看到第一种是to的字符串写法后面两种是to的对象写法
!-- RouterLink to/community active-classactive classnavi-style社区/RouterLink --!-- 里面只能用单引号 --
!-- RouterLink :to{path:/community} active-classactive classnavi-style社区/RouterLink -- RouterLink :to{name:shequ} active-classactive classnavi-style社区/RouterLink
嵌套路由
要实现的效果点击社区模块显示所有的帖子点击帖子标题在下方显示帖子的详情 1.编写Post.vue
2.将Post.vue 配置成Community.vue的子路由
const routercreateRouter({history:createWebHistory(),routes:[{path:/community,name:shequ,component:community,//配置子路由children:[{path:post,name:tiezi,component:post}]},{path:/friend,component:friend},{path:/home,component:home}]})export default router
3.在Community中写跳转
前两种都要加完整路径
!-- 社区模块 --
templateh2社区模块/h2li v-forpost in postList :keypost.postId!-- RouterLink to/community/post{{ post.title }}/RouterLink --!-- RouterLink :to{path:/community/post}{{ post.title }}/RouterLink --RouterLink :to{name:tiezi}{{ post.title }}/RouterLink/lirouter-view/router-view/templatescript langts setupimport { onMounted,onUnmounted } from vue;let postList[{postId:1,title:今天天气真好,content:我想出去玩},{postId:2,title:最近有电影好看,content:推荐一下},{postId:3,title:再也不万元神了,content:是不可能的},{postId:4,title:一眼顶针,content:鉴定为假},{postId:5,title:哈哈哈哈,content:1234889}]//切换到这里挂载切换到别的view被卸载onMounted((){console.log(community被挂载了)})onUnmounted((){console.log(community被卸载了)})/script
路由传参
query参数传递
传递参数
!-- 传死数据 --!-- RouterLink to/community/post?postId1title去干嘛content114514{{ post.title }}/RouterLink --!-- 模板字符串嵌入js --!-- RouterLink :to/community/post?postId${post.postId}title${post.title}content${post.content}{{ post.title }}/RouterLink --!-- 携带query参数 --RouterLink :to{path:/community/post,query:{postId:post.postId,title:post.title,content:post.content}}{{ post.title }}/RouterLink
接收参数
templatediv classpost-contentulliid: {{route.query.postId }}/lili标题: {{ route.query.title }}/lili内容: {{ route.query.content }}/li/ul
/div/templatescript langts setup//注意是useRoute 不是useRouterimport { useRoute } from vue-router;const routeuseRoute()/script
param参数传递
传递参数
首先需要在路由规则里面添加占位
//param参数占位版children:[{path:post/:postId/:title/:content?, //content加个表示可选name:tiezi,component:post}]
!-- 传死数据 --!-- RouterLink to/community/post/1/出去玩/谁一起{{ post.title }}/RouterLink --!-- content是可选的 --!-- RouterLink to/community/post/1/出去玩{{ post.title }}/RouterLink -- !-- 模板字符串嵌入js --!-- RouterLink :to/community/post/${post.postId}/${post.title}/${post.content}{{ post.title }}/RouterLink --!-- 携带param参数 用param传递参数时,必须使用 name --RouterLink :to{name:tiezi, //养成习惯用单引号params:{postId:post.postId,title:post.title,content:post.content}}{{ post.title }}/RouterLink
接收参数
templatediv classpost-contentulliid: {{route.params.postId }}/lili标题: {{ route.params.title }}/lili内容: {{ route.params.content }}/li/ul
/div/templatescript langts setup//注意是useRoute 不是useRouterimport { useRoute } from vue-router;const routeuseRoute()/script
路由的props配置
作用用于简化接收数据的写法
1.param 2.query (当然param也可以这么写) replace属性 作用控制路由跳转时操作浏览器历史记录的模式。浏览器的历史记录有两种写入方式分别为push和replace
push是追加历史记录默认值。replace是替换当前记录。
在默认的push模式下可以点击按钮回滚 开启replace 回滚不了了 路由编程式路由导航
我们前面写的代码只能通过RouterLink标签实现路由跳转假设我们要实现一个登录功能会发现我们根本实现不了这个功能因为RouterLink是个标签不能放在函数里而我们进行逻辑判断肯定要用到方法。 一个小案例
用button实现和下面RouteLink一样的效果
button clickshowPost(post)使用编程式导航来跳转路由显示帖子内容/buttonRouterLink :to{path:/community/post,query:{postId:post.postId,title:post.title,content:post.content}}{{ post.title }}/RouterLink
1.拿到路由器对象
import { useRouter } from vue-router;const routeruseRouter()
2.要跳到哪里传什么参数(原来 :to 里面怎么写这个里面就怎么写)
function showPost(post:any){router.push( {path:/community/post,query:{postId:post.postId,title:post.title,content:post.content}})}
选择router.push 或router.replace 决定是否能回溯
测试点击按钮一样能实现之前的效果 路由重定向
作用将特定的路径重新定向到已有路由。
案例
需求刚进来啥也没有我想要刚进来就显示社区的内容 在路由器中定义一条新路由 这条路由会在访问 的时候重定向路由到 这样我们一登录成功就能看到社区的帖子了 pinia
搭建pinia环境
1.引入依赖
npm i pinia 2.在main.ts中引入pinia 准备一个基本的效果
templateh2测试一下pinia/h2brspan当前求和为{{ sum }}/spanbrselect v-model.numbernoption value11/optionoption value22/optionoption value33/option/selectbutton clickadd加/buttonbutton clickminus减/button
/templatescript langts setupimport { ref } from vue;let sumref(0)let nref(1)function add(){sum.valuen.value}function minus(){sum.value-n.value}/script
1.存储读取数据
在src文件夹下定义一个store文件夹 count.ts
import { defineStore } from pinia;//定义并暴露一个store 第一个参数是id
export const useCountStoredefineStore(count,{//数据state() {return{sum:0,n:1}},//方法actions:{},})
用pinia读取数据 2.修改数据
修改数据的三种方式如下
templateh2测试一下pinia/h2brspan当前求和为{{ countStore.sum }}/spanbrselect v-model.numbercountStore.noption value11/optionoption value22/optionoption value33/option/selectbutton clickadd加/buttonbutton clickminus减/buttonbrbutton clickchange修改pinia里面的数据/button
/templatescript langts setupimport { ref } from vue;import { useCountStore } from ../store/count;
import { sum } from element-plus/es/components/table-v2/src/utils.mjs;let countStoreuseCountStore()function add(){countStore.sumcountStore.n}function minus(){countStore.sum-countStore.n}function change(){//1.直接修改//countStore.sum666//2.批量修改
/* countStore.$patch({sum:999,n:88} ) *///3.借助action修改action中可以编写一些业务逻辑 countStore.Multiply(10) }/script
count.ts
import { defineStore } from pinia;//定义并暴露一个store 第一个参数是id
export const useCountStoredefineStore(count,{//数据state() {return{sum:0,n:1}},//方法actions:{Multiply(value:number){this.sum*value}},})
3.storeToRefstoRefs
借助storeToRefs将store中的数据转为ref对象方便在模板中使用。注意pinia提供的storeToRefs只会将数据做转换而Vue的toRefs会转换store中的所有进行转换(包括数据和方法而方法是不需要我们进行转换的)
4.getterscomputed
定义 使用 这个东西相当于前面学过的computed
5.$subscribe的使用watch
通过 store 的 $subscribe() 方法侦听 state 及其变化
//mutate:本次修改的信息//state发生了什么变化countStore.$subscribe((mutate,state){console.log(这个仓库里面的数据发生了改变,mutate,state)})
点击”加“按钮 这个东西相当于前面学过的watch
tips
1.快捷键
altshift 多行写
altshifta 注释
shift 用包裹
2.别名插件
引入一个拓展插件让Hello.vue被引入App.vue的时候可以起别名 在vite.config.js中引入 3.v-model适用表单元素和v-bind(适用表单属性)
数据绑定方向 v-model是双向数据绑定。它不仅能够将 Vue 实例中的数据渲染到页面上还能够监听用户的输入并将用户输入的数据更新回 Vue 实例中的数据。这种双向绑定特别适用于表单元素如 input、select 和 textarea。 v-bind是单向数据绑定。它主要用于将 Vue 实例中的数据绑定到 HTML 元素的属性上但不会自动将用户输入的数据更新回 Vue 实例。虽然通过配合事件处理可以实现双向绑定但 v-bind 本身只负责单向的数据流。
适用范围 v-model主要用于表单控件或自定义组件的双向数据绑定。它会自动根据控件类型如文本、单选按钮、复选框、选择框等选择正确的方法来更新元素。 v-bind几乎可以用于绑定任何 HTML 元素的属性包括但不限于 class、style、href、src 等。此外它还可以用于绑定表达式和 HTML 内容尽管绑定 HTML 内容时需要使用不同的语法。