VUE3的学习笔记【从啥也不会到起码看得明白】
枯燥的开头,勇敢迈出第一步:
main.js是我们项目的入口文件不要写太多东西
现在用的是vite式的!!!
【
创建一个Vue应用前提已经安装高版本的Node.js
创建的项目将使用基于Vite的构建设置,并允许使用Vue的单文件组件SFC
命令行中运行npm init vue@latest
这一指令将会安装并执行create-vue,vue官方的项目脚手架工具。
出现一些选项不确定是否开启某个功能的话直接按下一系列回车或选择No
项目被创建之后
cd 项目名称
npm install
npm run dev
现在成功创建组合式API和<script setup>而非选项式API
{当准备将应用发布到生产环境时,运行npm run build在。dist文件夹中创建
】
【一些多写点代码就自然而然理解看起来很干的理论,但是当时生怕错过就完了】
每个Vue应用都是通过createApp函数创建一个新的应用实例
vue主要是实现了动态展示的一个效果不需要转换切换了/路径然后及时显示
逻辑部分:
<script>
const Counter={//配置对象
data:function{
return{
num:0
uname:”张三”
id:
url:
};
},
methods:{
//给vue定义方法
changeUname:function(){
//this指向vue实例
this.uname=”李四”;
},
changeColor:function(){
this.id=’d2’
}
},
};
create(App).mount(‘#count’)
//创建应用,将配置对象传入,使用mount将其挂载【及时div】和上面的元素相关联
</script>
导航栏那里的App.vue就是显示用的是组件,现在还没开始学setup那个组合组件部分
【看到这里还是不理解的话也没事,继续往下】
类似于export default这是声明式渲染
与methods方法、mounted声明周期函数并列关系
proxy:代理。可以理解为一个拦截器,当我们操作对象时它会对对象进行拦截,从而进行检测和改写。它存在13中捕获器类型,常用的有has(),get(),set(),deleteProperty(),construt()和apply()主要用于函数
组件实例property:所有的无论如何定义都可以在组件模板被访问
采用mustache语法就是{{}双大括号
<span>Massage:{{uname}}</span>
mustache标签会被替代为组件中定义的值
methods给vue定义方法
<template>
<div>
<p>{{num}}</p>
<p>{{uname}}</p>
<p v-once>{{uname}}</p>
<boutton @clilck=”changeUname”>改变名字</button>
<p> {{msg}}</p>
v-html,让内容以html的形式实现
<p v-html=”msg”></p>
v-bind:动态的绑定属性内容
<p v-bind:id=”id”>v-bind的绑定</p>
<img v-bind:src=”url” alt=”” />
</div>
</template>
<style>
#id {
color:red;
}
#d2 {
color:bule;
}
</style>
迄今为止,在我们的模板中,我们一直都只绑定简单的property键值,但实际上对于所有数据的绑定,vue都提供了完整的js表达式支持
同样的位置加入一个改变颜色的按钮
<button @click=”id=’d2’”’>改变颜色</button>
意味着对于一些简单事件不需要重新定义的时候就可以用上面的方法
使用js表达式
<p>{{num+1}}</p>
实现张三的反转,先分隔为字符然后reverse实现数组的逆序输出
<p>{{uname.split(‘’).reverse().join(‘’)}}</p>
<p v-bind:id=”id+1”>v-bind绑定</p>
指令(Directives)是带有v-作为前缀的特殊指令attribute,该指令的预期值是单个JS表达s式。v-for和v-on是例外情况。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式的作用于DOM
一些指令能够接受参数,在其后以:表示
v-on:用于监听DOM事件可直接用@代替
同样的还有v-bind等价于:就是这个冒号
下面介绍[动态内容]
动态参数:
<p v-bind:[attributeName]=”id”>v-bind绑定</p>
动态属性:
<button @click=”attributeName=’calss’”>改变属性</button>
动态事件:
<button @[mouseEvent]=”attributeName=’class’”>改变属性</button>
<button @click=”mouseEvent=’mouseover’>改变事件</button>
背景:
attributeName:’id’
mouseEvent:”click”
因为使用到了classs所以添加.引导的类选择器
.id{
font-size:50px;
}
以上模板语法讲解的差不多了
下面是Data property和方法
组件的data是一个函数,Vue会在创建新组件的过程中调用此函数,它应该返回一个对象,然后Vue会通过响应性系统将其包裹起来,并以¥data的形式存储在组件中,为方便起见,该对象的任何顶级property也会直接通过组件实例暴露出来。
这些实例property仅在首次创建时被添加,所以要在data函数中定义,必要是也就是还没赋值时会使用null,undefind或其他占位值
直接将不包含在data中的新property添加到组件实例是可行的,但由于property不在背后响应式$data对象内,所以Vue的响应系统不会自动跟踪它
Vue使用$前缀通过组件实例暴露自己的内置API.它还为内部的property保留_前缀,当避免使用这两个字符开头的顶级dataproperty名称。
方法
我们使用methods选项向组件实例添加方法,它应该是一个包含所需方法的对象:
Vue自动为它绑定this,以便它始终指向组件实例。这将确保方法在用作事件监听或回调时保持正确的this指向。在定义methods时避免使用箭头指向
和其他所有的property一样可以在组件中被访问,在模板中,通常被当做事件监听使用
对于任何包含响应式数据的复杂逻辑,应当使用计算属性:
computed:{
}
它拥有一个缓存,只要依赖值不变就不会重新经计算
比如说1+3
要输出三次结果采取调用方法的形式就需要计算三次但是它就一次,缓存以提高性能
computed:{
reverseMsg:function(){
console.log(“计算属性”);
retrun this,message,split(‘’),reverse().join(“”)
}
},
methods:{
reverseMsg:function(){
console.log(“计算属性”);
retrun this,message,split(‘’),reverse().join(“”)
}
},
这里是style的多种使用方式:
<script>
export default {
DataTransfer() {
return {
activeColor:'red',
fontSize:'50px',
bgColor:'pink',
//以上是直接在标签里使用时定义的属性值
styleObj: {
color:'red',
fontSize:'50px',
'background-color':'pink' ,
}
};
},
};
</script>
<template>
<div>
<!--第一种放置字符串-->
<p style="color:red">Hello</p>
<!--第二种放置对象,:即是通过v-bind绑定-->
<!--CSS property名可以用驼峰式(camelCase)或短横线分隔(记得用引号括起来)-->
<!--<p :style="{key(css属性名):value(属性值,来自于data中的属性)}"></p>-->
<p :style="styleObj">hello</p>
<!--用数组的形式-->
<p :style="[styleObj,{border:'5px solid blue'}]"></p>
</div>
</template>
<style>
</style>
下面是条件渲染:(v-if,v-show)
<script>
export default {
data(){
return{
age:20,
sex:'F',
isShow:true
}
}
};
</script>
<template>
<div>
<!--面临不同的选择我们需要根据不同的条件显示不同的样式所以就
引入条件渲染v-if和v-show-->
<p v-if="true">我是成年人了</p>
<p v-if="false">我还是个小朋友</p>
<p v-if="age>18">要对自己负责啦</p>
<p v-else-if="age==18">刚满18岁</p>
<p v-else>还可以耍赖</p>
<!--只显示为真的值-->
<!--在template上渲染条件分组,它的包裹是不显示<template>的可以大范围使用if来控制的效果-->
<template v-if="age>=18">
<p>你好</p>
<p>成年人总是有很多烦恼只能自己消化</p>
<p>今天也要加油努力赚钱买房</p>
</template>
<!--v-show-->
<p v-show="sex=='F'">女生</p>
<P v-show="sex=='M'">男生</P>
<!--不同的是v-show元素始终会被渲染并保留在DOM中,它只是简单的切换
display CSS的属性,不支持<template和v-else-->
</div>
</template>
<h2 v-if="isShow">标题内容1之v-if</h2>
<h2 v-show="!isShow">标题内容2之v-show</h2>
<!--这里即是是条件不符合的情况下v-show标签依然再只是属性上display:None
而v-if每一次都是合理才渲染创建出来,控制DOM元素的创建和销毁的
总之频繁切换用v-show,条件少则反之-->
<button @click="isShow=!isShow">改变isShow</button>
<style>
</style>
列表渲染v-for,如果想要把一个数组中的元素全部渲染出去是要用到for循环:
<script>
export default {
data(){
return{
person:['张三','李四','王二'],
personObj:{name:'张三',age:18,sex:'男'}
};
},
//写方法添加一个人
methods:{
addPreson:function(){
this.person.unshift('赵六')
}
}
};
</script>
<template>
<ul><!--v-for使用数组,item代表数组中的每一个元素,可见items就是数组名字,index是数组下标-->
<li v-for="item in person" :key="item">{{item}}</li>
<!--输出结果是一整个数组的元素-->
</ul>
<ul>
<li v-for="(item,index) in person" :key="index">{{item}}-->{{index}}</li>
<!--输出结果是一整个数组的元素和对应的012索引-->
</ul>
<!--输出结果是一整个数组的元素,这里的in可以换成of-->
<!--v-for使用对象,item表示的是键值,key表示键名-->
<ul>
<li v-for="(item,key,index) in personObj" :key="index">{{item}}-->{{key}}-->{{index}}</li>
</ul>
<ul>
<li v-for="item in person" :key="item"><input type="checkbox" name="" id=""></li>
<!--输出结果是一整个数组的元素前面加了可选框-->
</ul>
<button @click="addPreson">增加</button>
</template>
<style>
</style>
【维护状态:为了给Vue一个提示,使它能够跟踪每个节点的身份
从而重用和重新排序现有的元素故需要为每项提供一个唯一的key值】
*比如在没写入key有红色下划线情况下运行,点击增加按钮之前我们先选中了张三,然后点击增加导致首部增加了赵六但是我们选的人变成了赵六,意味着实际上只是选中它的索引值并没有实时根究
数组的更新操作:
<script>
import { reverse, sortBy } from 'lodash';
export default {
data(){
return{
list:[1,2,3,4,6,5],
};
},
methods:{
changeList:function(){
//当然可以像通过索引值去改变数组 this.list[5]=7这在vue2中是做不到的
// push()数组末尾添加元素,可以一个以上
//this.list.push(7,8,9)
// pop()删除数组末尾的元素
shift();//一样的格式删除数组的第一位元素
unshift();//从数组的首尾添加元素,可以一个以上(0,9,9)
splice();//常用删除,插入,替换都OK,3个参数
//(删除对象的下标,要删除的个数默认全部)
//(插入对象的下标,传入0,接上要插入的所有元素)eg:插入789在1 的位置this.list.splice(1,0,7,8,9)
//(替换对象开始的下标,替换的个数,替换为些啥)(1,3,7,8,9)也可以理解为删除了3个后插入7,8,9
sort();//排序
reverse();//字符串转数组然后翻转
},
},
};
</script>
<template>
<div>
<ul>
<li v-for="item in list" :key="item">{{item}}</li>
</ul>
<botton @click="changeList">改变数组</botton>
</div>
</template>
<style>
</style>
事假处理:
【监听事件:使用v-on即@符号来监听DOM事件并在触发事件时执行一些JavaScript.用法为v-on:click=”methodsName”或使用快捷键方式@click=”methodsName”】
<script>
import { reverse, sortBy } from 'lodash';
export default {
data(){
return{
counter:0
};
},
methods:{
addCounter(){
this.counter++
}
},
};
</script>
<!--绑定事件JS直接应用-->
<h2 @click="counter++">{{counter}}</h2>
<!--绑定事件函数处理,没有传入参数情况-->
<h2 @click="addCounter">{{counter}}</h2>
methods:{
addCounter(number){
this.counter+=number
}
},
<!--传参数-->
<h2 @click="addCounter(5)">{{counter}}</h2>
-------------------------------------------------------------
methods:{
addCounter(e){
this.counter++;
console.log(e)
}
},
};
</script>
<template>
<div>
<!--绑定事件函数处理,没有传入参数情况,控制台接收事件e-->
<h2 @click="addCounter">{{counter}}</h2>
<!--有时需要联系在内联语句处理器中访问原始的DOM事件,可以用特殊变量$event传入-->
methods:{
addCounter(number,e){
this.counter+=number;
console.log(e)
}
},
};
</script>
<template>
<div>
<!--绑定事件函数处理,传入参数情况,控制台接收事件e-->
<h2 @click="addCounter(5,$event)">{{counter}}</h2>
事件修饰符:
【在事件处理程序中调用event.preventDefault()或event.stopPropagation()是非常常见的需求。尽管我们可以轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理DOM事件细节。故v-on提供了事件修饰符,修饰符是由点开头的指令后缀来表示的】
methods:{
addCounter(number,e){
this.counter+=number;
console.log(e)
},
addAge(){
this.age++
},
divClick:function(){
console.log(‘父元素展示’);
}
btnClick:function(){
console.log(‘子元素展示’);
}
<!--事件修饰符
.stop阻止事件冒泡
.prevent阻止默认行为(比如说做完一件事点击按钮提交跳转,偏要自己提交控制台返回)
.once只触发一次回调(这个魔法只能使用一次)
-->
<div @click=”divClick”>
<button @click.stop=”btnClick”>按钮</button>
在methods中定义:
submitClick:{
console.log(‘提交数据成功’);
}
<form action=””>
<input type=”submit” value=”提交” @click.prevent=”submitClick”>
</form>
onceClick:function(){
console.log(‘只会触发一次’);
}
<button @click=”onceClick”>这个魔法只能用一次</button>
按键修饰符:
<script>
import { reverse, sortBy } from 'lodash';
export default {
data(){
return{
};
},
methods:{
keyUp:function(){
console.log('键盘被按下了,数据提交成功');
}
},
};
</script>
<template>
<div>
<!--.{keyCode(键盘编码)| KeyAlias (键盘的简写)}监听键盘的某个键帽-->
<input type="text" @keyup="keyUp">
<!--这里没有定义的话输入啥都会触发控制台看到log内容,下面是在点到enter之后触发提交数据成功-->
<input type="text" @keyup.enter="keyUp">
</div>
</template>
表单输入绑定:
【使用v-modle指令在表单<input>,<textarea>及<select>元素上创建双向数据绑定,它会根据控键类型自动选取正确的方法来更新元素,尽管有些神奇,但本质上不过是语法糖(:, @),它负责监听用户输入的事件来更新数据,并在某种极端场景下进行一些特殊处理】
接下来我们实现以下效果:
Ta-da:
<script>
export default {
data(){
return{
msg:"helloWorld"
};
},
};
</script>
<template>
<div>
<input type="text" v-model="msg">
<h2>{{msg}}</h2>
</div>
</template>
*原理两个属性构成:
v-bind绑定一个value属性
v-on给当前的元素添加一个input事件
等价于:
V-model的使用:【选择,勾选,单选框多选框】
<script>
export default {
data(){
return{
msg:"helloWorld",
checked:"",
fruits:[],
sex:'男',
city:"",
citys:[]//通过ctrl键控制多选
};
},
};
</script>
<template>
<div>
<input type="text" v-model="msg">
<h2>{{msg}}</h2>
<!--复选框(只有一个框时v-model默认值为布尔值)-->
<input type="checkbox" v-model="checked">
<h2>{{checked}}</h2>
<!--多个勾选框-->
<input type="checkbox" v-model="fruits" value="苹果">苹果
<input type="checkbox" v-model="fruits" value="柚子">柚子
<input type="checkbox" v-model="fruits" value="草莓">草莓
<input type="checkbox" v-model="fruits" value="西瓜">西瓜
<input type="checkbox" v-model="fruits" value="哈密瓜">哈密瓜
<input type="checkbox" v-model="fruits" value="荔枝">荔枝
<h2>喜欢的水果是{{fruits}}</h2>
<!--单选框 value控制好互斥形式就省略了name=sex-->
<input type="radio" v-model="sex" value="男">男
<input type="radio" v-model="sex" value="女">女
<h2>{{sex}}</h2>
<!--选项框 单选-->
<select name="" id="" v-model="city">
<option value="昆明北">昆明北</option>
<option value="长沙南">长沙南</option>
<option value="南昌西">南昌西</option>
<option value="上海虹桥">上海虹桥</option>
</select>
<!--多选框 加上multiple-->
<select name="" id="" v-model="citys" multiple>
<option value="昆明北">昆明北</option>
<option value="长沙南">长沙南</option>
<option value="南昌西">南昌西</option>
<option value="上海虹桥">上海虹桥</option>
</select>
<h2>{{citys}}</h2>
</div>
</template>
对应效果:
v-model的修饰符:(表单输入绑定)
<input v-model.lazy=”msg” />
*这时失焦,在输入框里输入修改并不会立刻事实更新,要移出框change后改变
.number将输入框中的内容自动转换为数字类型
.trim自动过滤用户输入的首尾空白符
组件基础:
开始啦:
[组件的首字母大写]
我们以.vue为组件,App.vue其实就是这里的根组件
[import 组件名 from’./路径/组件名.vue’]
<script>
import BlogPost from'./views/BlogPost.vue'
export default {
data(){
return{
};
},
components:{
BlogPost
}
};
</script>
<template>
<div>
<BlogPost></BlogPost>
</div>
</template>
新建的BlogPost.vue:
<template>
<div>
<h4>我是组件内容</h4>
</div>
</template>
输出:
父组件和之组件:
组件是带有名称可复用的实例,单独功能模块的封装
封装为一个组件呢方便复用
组件数据的存放
让每一个组件对象都返回一个新的对象,不会造成数据污染
如果上面return的是obj会导致一改全改
父传子通过prop传值:【根组件向下】
早些时候,说创建了一个博文组件的事情,问题是如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的,这也正是prop的由来
Prop是你可以在组件上注册的一些自定义attribute,为了给博文组件传递一个标题,我们可以使用props选项将其定义在该组件可接受的prop列表中。
1.数组式接收:
- props:{
//对象形式
//可以限制类型
//message:string
//属性和默认值
message:{
type:String,
default:”你好”
required:true//设置为必传属性
}
}
当一个值被传递给一个prop attribute时,它就成为该组件实例中的一个property,该property的值可以在模板中访问,就像其他任何proeperty一样,一个组件可以拥有任意数量的prop值,并且在默认情况下,无论任何值都可以传递给prop
[为什么要这样传呢,因为拆分]
B站网课保姆级教程真的讲得很好~
【太多了跟不上老师进度,但是目前影响不大】
先跳过一部分:
子组件通过自定义事件向父组件传值
父组件访问子组件$refs
子组件访问父组件和根组件$parent
插槽的基本使用
具名插槽的使用
插槽备用内容和作用域插槽的使用
组件之间的跨级通信provide和inject
vue生命周期图示讲解
vue生命周期钩子函数的基本使用
vue3组合式API初体验
$$$下面是路由:
在终端进行启动之后安装
(在命令行中输入)
npm install vue-router@4
路由的核心:改变URL,但是页面不进行整体刷新
路由理解为指向
路由表,是一个映射表,一个路由就是一组映射关系,key:valeu,
key:表示路由
value:表示function
在终端进行启动之后安装
router-link:
注意,我们没有使用常规的a标签,而是使用一个自定义组件router-link来创建连接。这使得Vue Router可以在不重新加载新页面的情况下更改URL,处理URL的生成以及编码。我们将在后面看到如何从这些功能中获益。
router-view:
将显示与URL对应的组件,你可以把它放在任何地方,以适应你的布局
JavaScript
- 定义路由组件
- 也可以从其他文件导入
【下面这个只是看看】
在App.vue中:
<script setup>
</script>
<template>
<div>
<!--vue-router是基于路由和组件的,路由是用来设定访问路径,将
我们的路径和组件映射起来,一个路径对应一个组件-->
<h1>Hello App!</h1>
<p>
<!--使用router-link组件进行导航-->
<!--通过传递to来指定连接-->
<!--<royter-link>将呈现一个带有正确href属性的<a>标签-->
<router-link to="/">Go to home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<!--路由出口-->
<!--路由匹配到组件将渲染在这里-->
<router-view></router-view>
</div>
</template>
<style>
</style>
之前有新建src/router/index.js
import { createRouter,createWebHashHistory } from 'vue-router'
//对路由进行一个集中管理
//1.定义路由组件
import Home from '../views/Home'
import About from '../views/About'
//2.定义一些路由
//每个路由都要映射到一个组件
//我们后面在讨论嵌套路由
const routes = [
{ path:'/', component: Home},
{ path: '/about', component: About},
]
//3.创建路由实例并传递'routes'配置
//你可以在这里输入更多配置,但我们在这里
//暂时保持简单
const router = createRouter({
history:createWebHashHistory(),
routes,
})
export default router
就差一句话真的
一般我们对应的路由组件都会放在src/views
其中建Home.vue和About.vue
在main.js中:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
//这里会自己默认index所以没写
import './assets/main.css'
//createApp(App).mount('#app')
const app=createApp(App)
app.use(router)//注意顺序先use
app.mount('#app')
//shift+ALT+R在文件资源管理器中打开
在package.json中出现下面这些:
"name": "router",
"version": "0.0.0",
我觉得很奇怪就把它删除了没出现什么强烈影响只是在npm run dev时少了一行router0.0.0。
====================
vue-router带参数的动态路由匹配(想拿到一个id或者是传参)
很多时候,我们需要给定匹配模式的路由映射到同一个组件,例如,我们可能有一个User组件,它应该对所有用户进行渲染,但用户的id不同,在Vue Router中我们可以在路径中使用一个动态字段来实现,我们称之为路径参数。
新匹配一个:
新建User.vue
在index.js中导入语句
import User from ‘../views/User.vue’
{path:’/user/:id,compoment: User},
在App.vue中调用
<router-link to="/user/123">Go to User</router-link>
现在像/user/johnery和/user/jolyne这样的URL都会映射到同一个路由
路径参数用冒号:表示,当一个路由被匹配时,它的params的值将在每一个组件中以this.$route.params的形式暴露出来,因此,我们可以通过更新User的模板来呈现当前的用户ID
<template>
<div>用户</div>
</template>
<!--vue2获取当前数据方式
<script>
export default {
mounted() {
//$route表示当前活跃的对象
console.log(this.$route.params.id);
},
}
</script>下面是组合式API获取-->
<script setup>
import { useRoute } from 'vue-router';
console.log(useRoute().params.id);
</script>
404Not Find页面
新建NotFind.vue
import { createRouter,createWebHashHistory } from 'vue-router'
//对路由进行一个集中管理
//1.定义路由组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import User from '../views/User.vue'//定义好之后传参
import NotFind from '../views/NotFind.vue'
//2.定义一些路由
//每个路由都要映射到一个组件
//我们后面在讨论嵌套路由
const routes = [
{ path:'/', component: Home},
{ path: '/about', component: About},
{ path:'/user/:id',component: User},
//所有都没匹配到再提示,使用正则的方式都匹配
{ path:'/:path(.*)',component:NotFind}
]
//3.创建路由实例并传递'routes'配置
//你可以在这里输入更多配置,但我们在这里
//暂时保持简单
const router = createRouter({
history:createWebHashHistory(),
routes,
})
export default router
新建News.vue
//正则限制动态路由的参数一定为数字
// { path:'/news/:id(\\d+)',component:News},
//多个参数/123/456,这里+换*(可重复)换?(一次)都表示参数可有可无
{ path:'/news/:id+',component:News},
]
嵌套路由:
新建Parent.vue
<template>
<div>父组件Parent</div>
<router-link to="/parent/style1">样式1</router-link>
<router-link to="/parent/style2">样式2</router-link>
<router-view></router-view>
</template>
这里是index.js中的改动
{ path:'/parent',component:Parent,
children:[
{
path:"style1",
component:Style1
},
{
path:"style2",
component:Style2
},
]
}
下面是两个子vue:
<template>
<div>
<p>样式1</p>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ol>
</div>
</template>
再新建Style2.vue:
<template>
<div>
<p>样式2</p>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
</template>
通过js跳转页面
编程式导航:[除了router-link外的另一种】
实现路由守卫:
在Vue实例中,可以通过$router访问路由实例,因此可以调用this .$router.push.
想要导航到不同的位置URL,可以使用router.push方法,它向history栈中添加一个新的记录,所以当用户点击浏览器后退时,会回到之前的URL.
****这里区分一下$route表示当前活跃的路由对象,有r全局无r当前****
新建Page.vue:
<template>
<div>
<h2>页面</h2>
<button @click="goPage">跳转页面</button>
</div>
</template>
<script>
export default {
methods: {
goPage:function(){
//if(123==123){}可以加上条件限制
this.$router.push('/')//跳转Home
}
},
}
</script>
正常的导入并配置index.js
App.vue中:
<h1>编程式导航</h1>
<router-link to="/page">Go to Page</router-link>
下面有多为index.js中News部分添加属性name:”news”
在Page.vue中试:
<template>
<div>
<h2>页面</h2>
<button @click="goPage">跳转页面</button>
</div>
</template>
<script>
export default {
methods: {
goPage:function(){
//if(123==123){}可以加上条件限制
//this.$router.push('/')//跳转Home
//this.$router.push({path:"/"})//通过传入对象,下面的带参数
//this.$router.push({path:"/user/123456"})
this.$router.push({name:"news",params:{id:123}})
//数据获取 this.$router.push({path:"/about",query:{name:"zhangsan}"}})
}
},
}
</script>
About.vue中观察:
<template>
<div>about</div>
</template>
<script>
export default {
methods() {
console.log(this.$route.query.name);
},
}
</script>
替换当前位置:
它的作用类似于router.push,唯一不同的是,它在导航时不会向history添加新纪录,正如它的名字所暗示那样------它取代了当前的条目。
声明式:<router-link:to=”...” repleace> 编程式:router.replace(...)
也可以直接在传递给router.push的routeLocation中增加一个属性replace:true
【这个替换很像覆盖的意思】
在以下两个vue中:
Page.vue中的改动是:
this.$router.push({path:"/about",query:{name:"zhangsan"}})
//替换当前位置
//this.$router.push({path:"/about",query:{name:"zhangsan"},replace:true});
//this.$router.replace({path:"/about",query:{name:"zhangsan"}})
在About.vue中的改动是:【增加了methods】
<template>
<div>about</div>
<button @click="goBack">后退</button>
</template>
<script>
export default {
mounted(){
console.log(this.$route.query.name);
},
methods:{
goBack(){
//前进传入的值为正值,后退传入的值为负值
this.$router.go(-1)
this.$router.back()//后退,等于go(-1)
this.$router.forward()//前进,等于go(1)
}
}
}
</script>
最后它的实现就相当于搜索框中的回退和前进箭头。体现在我们增加的About中按钮上。
命名路由和命名视图:
除了path之外,你还可以为任何路由提供name,这有以下优点:
没有硬编码的URL
params的自动编码解码
防止你在URL中出现打字错误
绕过路径排序
要求我去访问一个同时渲染出多个视图出来:
【如果不是在练习通常会分开写,首页的话会新建一个文件放在Home,然后会在component中放一些公共组件】
下面新建了三个.vue
ShopTop.vue
ShopMain.vue
ShopFooter.vue都是以下格式内容:
关键点在index.js与App.vue:
首先是3个import
{
path:"/shop",
components:{//注意因为要渲染多个所以这里有+s
default:ShopMain,
//关于缩写leftSidebar:leftSidebar可为leftSidebar,
ShopTop:ShopTop,
ShopFooter:ShopFooter
//这里就涉及到给router-view渲染出口名字
}
然后App.vue给出口:
<router-view name="ShopTop"></router-view>
<router-view></router-view>
<router-view name="ShopFooter"></router-view>
************很重要我忘记+s
重定向和别名:
【期待是首次打开就可以进入首页尽管导航栏路径是’/’或者还再次输入/home】
则在index.js的routes数组中增加定义:
下面两种方法都可以:
{
path:"/",
//重定向
// redirect:'/home'//当然这里要为以有的
//命名路由
redirect:{name:"home"}
}
甚至是用箭头函数的方法:
起别名:
path:'/parent',
alias:'/father',//这就是起别名的语句
//别名数组alias:['/father','/mother'],
路由组件传参:
【将props传递给路由组件,在你的组件中使用$route会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的URL,虽然这不一定是件坏事,但我们可以通过props配置来解除这种行为】
那些123其实都是string型
{
path:'/user/:id',
component: User,
props:true
},
两种写法:
<!--vue2获取当前数据,选项式方式
<script>
export default {
props:['id'],
mounted() {
//$route表示当前活跃的对象
console.log(this.$route.params.id);
console.log(this.id);//接收到传递的参数
},
}
</script>-->
<!--下面是组合式API获取-->
<script setup>
import { useRoute } from 'vue-router';
console.log(useRoute().params.id);
const props= defineProps({
id:String
})
console.log(props.id);
</script>
下面是接收一下:
注意先修改path:”/shop/:id”
上面这个在三个vue中都复制一下。
下面这个添加后拿不到但是该上面的False为true就拿得到了!传参能不能获取取决于它bool值啦
不同的历史模式:【两种路由模式】
Hash模式(改变路径产生变化但不会向服务器发送请求)
HTML5模式没有在路径中带#很好看但是没有适当的配置就会报404错误
《区别就是一个有#号一个没有》
引入history,更改,保存,重启终端:
64.路由守卫:
就像生命周期一样它也是一个函数,如果触发就执行,正如其名vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航,这里有很多但是植入路由导航中,全局的,单个路由共享的,或者组件级的。
全局前置守卫:
你可以使用router.beforeEach注册一个全局前置守卫
当一个导航触发时,全局的前置守卫按照创建顺序调用,守卫是一步解析执行,此时导航在所有守卫resolve完之前一直处于等待中。
每个守卫方法接收两个参数:
to:即将要进入的目标,用一种标准化的方式
from:当前导航正要离开的路由
返回false取消
对于index.js:
//全局守卫
router.beforeEach((to,from,next)=>{
console.log(to);
console.log(from);
next()//通行证
})
单路守卫:
{
//单个守卫比较常见是在登录界面+后台返回token
path: '/about',
component: About,
beforeEnter:(to,from,next)=>{
console.log(to);
console.log(from);
//每路守卫
if(123===123){
next()
}
}
},
组件守卫:
最后,你可以直接在路由组件中定义路由导航守卫(传递给路由配置的)
可用的配置API
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
<template>
<div>新闻</div>
</template>
<script>
export default {//想要拿到参数须遵循的模板,vm自定义的相当于this
data() {
return{
age: 18,
};
},
beforeRouteEnter(to,from,next){
console.log(to);
console.log(from);
next((vm)=>{//通过回调函数
console.log(vm.age);
})
console.log('路由组件进入之前');
},
beforeRouteUpdate() {
console.log('路由组件更新之前');
},
beforeRouteLeave() {
console.log('路由组件离开之前');
},
}
</script>
-----------------------------------------
路由懒加载:
比如说要在这里的index.js中导入特别多的文件,就靠它。
当路由被访问的时候才动态加载,此前我们用的都是静态的
const Home=()=>import("../views/Home.vue")
将import语句替换为上
Vue3如何进行状态管理【共用的数据集中管理】
//provide/inject跨级通信
下面用一整个新的大文件从新开始撸啦:
App.vue:
<script>
//vue3如何设置状态管理
//provide/inject跨级通信
import Home from './views/Home.vue'
import store from './store/index'
export default{
provide:{
store
},
components:{
Home//注册一下如果是组合式API的话其实是不用注册的
}
}
</script>
<template>
<Home />
</template>
<style>
</style>
新建了store/index.js:
//store仓库[小项目不用veux时]
//1.数据实现响应式
//在setup中有提到过ref reactive-->对象中存储状态msg,age,counter
import {reactive} from 'vue'
const store={
state:reactive({//定义状态
msg:"helloworld"
}),
updateMsg:function(){
this.state.msg='你好'
}
}
//2.如何在App组件通过provide提供
export default store
views/Home.vue:
<template>
<div>
<div>{{store.state.msg}}</div>
<button @click="updateMsg">改变msg</button>
</div>
</template>
<script>
export default {
inject:['store'],//注入
methods:{
updateMsg:function(){
this.store.updateMsg();
}
}
}
</script>
如何用fetch获取数据:
现在给个URL地址:http://localhost:3001/banner【这是别人本地服务器中的数据】
那在原生js或jquery中的话是通过阿贾克斯实现我们的数据交互,向后台发送请求的
fecth也是属于一种http数据请求方式,是原生JS
<template>
<div>
<div>{{store.state.msg}}</div>
<button @click="updateMsg">改变msg</button>
</div>
</template>
<script>
export default {
inject:['store'],//注入
created(){//生命周期里面
//返回promise对象
fetch('http://localhost:3001/banner').then((res)=>{
//console.log(res.json());//通过.json将响应回来的body解析为promise
return res.json()
}).then((res)=>{
console.log(res);
})
},
methods:{
updateMsg:function(){
this.store.updateMsg();
}
}
}
</script>
这节课我没上完大概是因为我没banner数据。
这里是Axios:
它是一个基于promise网络请求库,作用于node.js和浏览器中,它是isomorphic的(级同一套代码可以运行在浏览器和node.js中)。在服务端它使原生node.js的http模块,而在客户端(浏览端)则使用XMLHttp Requests
npm install axios
npm run dev
<template>
<div>
<div>{{store.state.msg}}</div>
<button @click="updateMsg">改变msg</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
inject:['store'],//注入
created(){//生命周期里面
//返回promise对象
//fetch('http://localhost:3001/banner').then((res)=>{
//console.log(res.json());//通过.json将响应回来的body解析为promise
// return res.json()
//}).then((res)=>{
//console.log(res);
//})
//基于promise的http库
axios.get('http://localhost:3001/banner').then((res)=>{
console.log(res);
})
},
methods:{
updateMsg:function(){
this.store.updateMsg();
}
}
}
</script>
【没有本地数据】
vite通过proxy代理,创建中转服务器,解决跨域问题
跨域请求数据是因为,浏览器同源保护策略的机制,通过proxy实现跨域请求数据
$$需要更改配置,找到vite.config.js文件:
¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
通过vue-cli创建项目:
Vue Cli是一个基于Vue.js进行快速开发的完整系统,之前我们是用的Vite
在终端执行:
npm install -g @vue/cli
通过vue --vesion 看版本
安装成功之后,创建一个项目:
vue create hello-world
=================================
VUE3通用后台管理系统
vue-cli的形式是可以通过选择的情况:比如要不要router选vue2还是vue3之类的,选好了以后page as 命名回车就可以直接用了,也可以选择保留一些常用要求
认识vuex:
vuex是专为Vue.js应用程序开发的状态管理模式+库,它采用集中式存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理应用包含以下几个部分:
状态,驱动应用的数据源;
视图,以声明方式将状态映射到视图
操作 响应在视图上的用户输入导致的状态变化
【将组件与组件之间的关系变成组件与仓库之间的关系】
========================================
Element Plus:
1全部引入
2局部引入
3手动导入
下面是项目的记录: