提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:以下是本篇文章正文内容,下面案例可供参考
BFC(block formatting context)块级格式化上下文,他是页面中的一块渲染区域,并且有一套属于自己的渲染规则,BFC 是一个独立的布局环境,具有BFC特性的元素可以看作是隔离的独立容器,容器里面的元素不会在布局上影响到外面的元素。
触发BFC:
使用场景
清除浮动:overflow:hidden(浮动塌陷,包含块没有设置高度或者是自适应的时候、包含块就不能撑起来,变成塌陷的状态。)
防止浮动文字环绕
解决边距重叠问题:根据 BFC 的定义,两个元素只有在同一BFC 内,才有可能发生垂直外边距的重叠,包括相邻元素、嵌套元素。
参考地址:juejin/post/6991867254803529765
定位 | 参考点 | 是否脱离文档流 |
---|---|---|
relative | 自己原来的位置 | × |
absolute | 包含块(第一个有定位属性的父元素) | √ |
fixed | 视口 | √ |
sticky | 最近的拥有滚动机制的祖先元素 | × |
固定定位和绝对定位后,元素变成定位元素:默认宽高由内容撑开,且依旧可以设置宽高。
transform 属性允许你对元素进行旋转、缩放、倾斜或移动等转换。
/* 将元素顺时针旋转45度 */
.element {
transform: rotate(45deg);
}
其他常见的 transform 函数:
translate(x, y):移动元素
scale(x, y):缩放元素
skew(x, y):倾斜元素
位移配合定位可实现水平垂直居中:
.box{
position : absolute;
left : 50%;
top : 50%;
transform : translate(-50%,-50%);
}
变换原点:transform-origin
元素变换时默认是元素的中心。transform-origin可以设置变换的原点。
修改变换原点对位移没有影响, 但是对旋转缩放会产生影响。
如果提供两个值,第一个是横坐标第二个是纵坐标。
如果只有一个值,另一个默认为50%。
3D变换的首要操作:父元素必须开启3D空间。
transition 属性用于控制元素状态变化时的过渡效果,例如在鼠标悬停时改变颜色、大小等。
.element {
background-color: lightblue;
transition: background-color 0.5s ease-in-out;
}
.element:hover {
background-color: lightgreen;
}
当你将鼠标悬停在 .element 上时,背景色将会在 0.5 秒内平滑地变为 lightgreen
keyframes 允许你定义一个动画序列,并通过 animation 属性将动画应用到元素上。@keyframes 定义了不同时间点的样式,animation 属性控制动画的持续时间、次数等。
/* 定义旋转和缩放的动画 */
@keyframes rotateScale {
0% {
transform: rotate(0deg) scale(1);
}
50% {
transform: rotate(180deg) scale(1.5);
}
100% {
transform: rotate(360deg) scale(1);
}
}
/* 将动画应用到元素 */
.animated-box {
width: 100px;
height: 100px;
background-color: lightcoral;
animation: rotateScale 2s infinite ease-in-out;
}
伸缩容器:开启了flex的元素
伸缩项目:伸缩容器的子元素自动成为伸缩项目。无论原来是哪种元素,一旦成为伸缩项目都会“块状化”。
flex实现水平垂直居中
.outer{
width:400px;
height:400px;
display:flex;
justify-content:center;
align-item:center;
}
.outer{
width:400px;
height:400px;
display:flex;
}
.inner{
wigth:100px;
height:100px;
margin:auto;
}
垂直水平居中的其他方法:
绝对定位元素的垂直水平居中
.parent {
position: relative;
height: 300px;
background: lightgray;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 关键 */
width: 100px;
height: 100px;
background: green;
}
适用于固定宽高的元素
.parent {
position: relative;
height: 300px;
background: lightgray;
}
.child {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
margin: auto;
width: 100px;
height: 100px;
background: purple;
}
伸缩性:
flex复合属性:复合flex-grow、flex-shrink、flex-basis三个属性
flex:1 意味着该项目会按比例扩展以占据容器的剩余空间,并在容器空间不足时按比例缩小
flex:1 和 flex:auto的区别:
flex:1 不考虑项目本身的大小,只根据剩余空间进行伸缩。
flex:auto 考虑项目本身大小同时也会根据剩余空间进行伸缩。
Less是CSS预处理器,是一种动态的样式表语言。
Less的特性包括变量(Variables)(@声明变量)、混入(Mixins)、嵌套(Nesting)、运算(Operations)、转义(Escaping)、函数(Functions)、命名空间和访问符、映射(Maps)、作用域(Scope)、注释(Comments)、导入(Importing)。
Sass是在服务端处理的,需要使用编译工具将Sass代码编译成CSS文件。
Less则需要在客户端使用JavaScript引入Less文件,并使用Less.js将Less代码编译成CSS文件。
短路运算:在逻辑与(&&)和逻辑或(||)的操作中,如果左边的表达式已经能够确定整个表达式的结果,那么就不会再去计算右边的表达式。
每一个javascript对象(除null外)创建的时候,都会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
blog.csdn/qq_34645412/article/details/105997336
将一个多维数组转换为一维数组。
可以通过递归、Array.propotype.flat()、或者通过reduce方法结合concat实现。
flat 方法可以接受一个可选的参数 depth,用来指定扁平化的深度。
不传参数或传 1 时,默认扁平化第一层嵌套数组。
传入数字 n 表示将数组扁平化到第 n 层深度。
如果传入 Infinity 作为参数,那么不管嵌套多深,都会被扁平化为一维数组。
let arr = [1,[2,[3,[4,5]]]];
console.log(arr.flat(1));//[1,2,[3,[4,5]]]
// 扁平化两层
console.log(arr.flat(2));//[1,2,3,[4,5]]
// 全部扁平化
console.log(arr.flat(Infinity));//[1,2,3,4,5]
递归
let arr = [1,[2,[3,[4,5]]]];
function flatten(arr){
let result = [];
for (let i = 0; i<arr.length;i++){
if(Array.isArray(arr[i])){
result = result.concat(flatten(arr[i]));
}
else{
result = result.concat(arr[i]);
}
}
return result;
}
console.log(flatten(arr));
reduce
reduce函数会遍历每一个元素,每次遍历都会执行一个回调函数,该函数有两个参数,一个是上一次回调函数返回的值,还有一个参数就是当前元素的值。可以给初始值,不给的话就默认初始值为第一个元素,然后从第二个元素开始遍历。最后返回最后一次回调函数返回的值。
let arr = [1,[2,[3,[4,5]]]];
function flatten(arr){
return arr.reduce((result,nowvalue)=>
Array.isArray(nowvalue)? result.concat(flatten(nowvalue)) : result.concat(nowvalue),[]);
}
console.log(flatten(arr));
offsetWidth:返回的是 元素的css宽度+padding+border+垂直方向滚动条的宽度(如果有)
clientWidth:padding+内容
内联元素以及没有 CSS 样式的元素的 clientWidth 属性值为 0。
scrollWidth:包括由于overflow溢出而在屏幕上不可见的内容。宽度与clientWidth一样
节流:n秒内只运行1次,如果重复触发只有一次生效。
防抖:n秒后执行该事件,如果n秒内重复触发,则重新计时。
节流:
由于 setTimeout 是异步执行的,它会在延迟之后调用 fn,而此时可能已经改变了 this 或者丢失了参数,所以需要提前保存这些信息,确保在 setTimeout 回调时能够正确使用。
function throttled(fn, wait){
let timer;
return function(){
let _this = this;
let args = arguments;
if(!timer){
timer = setTimeout(function(){
timer = null;
fn.apply(_this, args);
},wait);
}
}
}
实际应用:滚动加载,加载更多或滚到底部监听 搜索框,搜索联想功能
防抖:
function debounce(func,delay){
let time;
return function (){
clearTimeout(time);
time = setTimeout((...args)=>{
func.apply(this,args);
}, delay);
}
}
实际应用:在搜索框输入时,可以防止每次按键都发送请求,而是等用户停止输入一段时间后再次发送请求。
手机号、邮箱验证输入检测、窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="search-input" placeholder="请输入关键字信息进行搜索">
<div id="search-result">搜索结果</div>
<script>
function debounce(func, delay) {
let time ;
return function(...args){
clearTimeout(time);
time = setTimeout(()=>{
func.apply(this, args);
}, delay);
}
}
function search(query){
const resultDiv = document.querySelector("#search-result");
resultDiv.innerHTML = `搜素结果:${query}`;
}
const debouncedSearch = debounce(search,1000);
document.addEventListener("DOMContentLoaded", ()=>{
const searchInput = document.querySelector("#search-input");
searchInput.addEventListener("input", ()=>{
const query = searchInput.value.trim();
if(query){
debouncedSearch(query);
}
});
});
</script>
</body>
</html>
浅拷贝:只复制对象的第一层属性,嵌套的对象仍然引用原始对象中的数据。
Object.assign()、展开运算符、Array.prototype.slice()等
深拷贝:不仅复制对象的所有属性,还包括所有嵌套对象的值,使得新对象与原始对象完全独立。
深拷贝常用:
let obj1 = { name :"Jia",info : {age:"24"}};
let obj2 = JSON.parse(JSON.stringify(obj1));
优点:适合处理简单的对象或数组
缺点:不能处理函数、symbol、undefined 等特殊类型。不能拷贝对象的原型链和循环引用对象。
function deepClone(obj){
if(obj === null || obj !=='Object' ){
return obj;
}
let copy = Array.isArray(obj) ? []:{};
for (let key in obj){
if(obj.hasOwnProperty(key)){
copy[key] = deepClone(obj[key]);
}
}
return copy;
}
缺点:
对于深度非常大的嵌套对象,递归可能会导致性能问题。
无法处理循环引用的对象结构。
穿插知识:hasOwnProperty:是用来判断一个对象是否有你给出的名称的属性或对象。但是无法检查原型链上的属性,该属性必须是对象本身的一个成员。
for in / for of的区别: for in 适合遍历对象,用于遍历对象的可枚举属性,返回的是键名或者下标。 for of 适合遍历可迭代对象(如数组、字符串、Map、Set等),返回的是元素值。
import _ from "lodash";
const obj = { a: 1, b: { c: 2 }, d: new Date() };
const copy = _.cloneDeep(obj);
console.log(copy);
console.log(copy.b === obj.b); // false
console.log(copy.d === obj.d); // false
闭包指有权访问另一个函数作用域变量的函数。
当一个函数嵌套另一个函数中时,内部函数可以访问外部函数的变量,即使外部函数已经返回了。这种情况下,内部函数就形成了一个闭包,他保留了外部函数的作用域链并且可以继续访问这些变量。
闭包容易导致内存泄漏。闭包中的变量存储的位置是堆内存。
function outfun(){
let age = 10;
function innerfun(){
age++;
return age;
}
return innerfun;
}
const add = outfun();
console.log(add());
实际应用:1. 数据封装和私有变量 2. 函数工厂 3.节流防抖 4. 事件处理 5. 在异步操作完成时维护状态。
undefined == false 结果为false
let list = [ 8, 8, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8];
let newList =[];
for (let i = 0;i<list.length;i++)
{
if(!newList.includes(list[i])){
newList.push(list[i]);
}
}
console.log(newList);
还可以传入第二个参数来指定从哪个索引开始搜索元素。
原因:js中数字是二进制浮点数保存的。0.1,0.2在这种在二进制中是无限循环的小数。
解决方法:
1)let和 const:具有块级作用域,let 用来声明变量可重新赋值,const 用来声明常量不可再次赋值。
2)箭头函数:新的函数声明方式,语法简洁。
3)模版字符串:字符串插值功能,可定义多行字符串。
4)解构赋值:是一种 JavaScript 表达式,它允许从数组或对象中提取属性或值,并将这些值赋给其他变量,
5)默认参数:函数参数可设置默认值,
6)扩展运算符:可以将数组展开为逗号分隔的参数序列,或者合并多个对象或数组。
7)类与模块:通过 class 关键字定义类,使用 import 和 export 来导入和导出模块
8)Promise:用于处理异步操作。
9)Symbol和迭代器:提供了一种新的原始数据类型和自定义迭代行为的方式。
10)新的数据结构:Map、Set。
11)其他:对象属性简写,属性和方法简写,提升了JavaScript 的编码效率和可读性。
void 是js 的一个关键词,它可以执行一个表达式,然后始终返回undefined。undefined 是js的一个全局变量,表示未定义。在ES5+中,undefined是只读的,但是在之前的版本ES3以前,是可以被重新赋值的。
-1 / 0: -Infinity 负数除以 0,结果趋向负无穷大
0 ÷ 0 :NaN 数学上0 ÷ 0是未定义的,所以 JavaScript 返回 NaN
1/0:正数除以 0,数学上趋向于 +∞,所以 JavaScript 返回 Infinity
额外:
console.log(Infinity / Infinity); // NaN
console.log(Infinity - Infinity); // NaN
console.log(0 * Infinity); // NaN
console.log(1 / Infinity); // 0
console.log(-1 / Infinity); // -0
const obj = { name: "Alice" };
console.log(Object.hasOwn(obj, "name")); // true ✅ 推荐(ES2022+)
console.log(obj.hasOwnProperty("name")); // true ✅ 旧版支持
console.log("name" in obj); // true(但会检查原型链)
function Parent() {
this.name = "Parent";
this.colors = ["red", "blue"];
}
Parent.prototype.getName = function() {
return this.name;
};
function Child() {}
Child.prototype = new Parent(); // 继承
Child.prototype.constructor = Child; // 修正构造函数指向
const child1 = new Child();
child1.colors.push("green");
console.log(child1.getName()); // "Parent"
console.log(child1.colors); // ["red", "blue", "green"]
const child2 = new Child();
console.log(child2.colors); // ["red", "blue"] ✅ 不受 child1 修改影响
共享属性问题:如果父类属性是引用类型(如数组),修改一个实例的属性会影响所有实例。
function Parent(name) {
this.name = name;
this.colors = ["red", "blue"];
}
function Child(name) {
Parent.call(this, name); // 继承
}
const child1 = new Child("Child1");
child1.colors.push("green");
console.log(child1.name); // "Child1"
console.log(child1.colors); // ["red", "blue", "green"]
const child2 = new Child("Child2");
console.log(child2.colors); // ["red", "blue"] ✅ 不受 child1 影响
无法继承父类的原型方法(如 Name)。
每个子类都有自己的父类副本,导致占用内存增加。
封装:把数据(属性)和行为(方法)封装到对象中,隐藏内部实现,只暴露必要的接口。
继承:子类(派生类)继承父类(基类)的属性和方法,JavaScript 使用 extends 关键字实现继承,子类可以使用 super() 调用父类的构造函数。
多态:相同的方法在不同类中具有不同的实现,使得调用同一方法时,表现出不同的行为。
async 关键字用于定义异步函数,返回 Promise
await 关键字暂停执行,等待 Promise 解析(只能在 async 函数内部使用)
解析→ 生成渲染树 → 布局 →绘制→复合
浏览器解析入口一定是一个html页面,html也是解析流程的入口。css和js相关文件或内容嵌套在html的多个地方,当解析到它们时,会立即停止html解析,进入css或者js的解析流程,解析完成之后再回到html解析流程。解析完成html文件最后一个标签,整个解析即结束。
html解析:解析html文本,生成html元素节点,识别html嵌套结构并构建DOM树
css解析:加载css资源,解析css文本,构建cssom树,样式规则计算
JS解析:加载js资源,解析js文本,构建结构树,解析优化代码
解析HTML:将字符串解析成DOM树和CSSOM树
样式计算:得到Computed Style
布局:产生布局树
分层:划分图层
绘制:产生绘制指令集
分块:划分区域
光栅化:生成位图
画:生成quad,提交硬件,完成成像
浏览器渲染
优化:
let frg = document.createDocumentFragment();
for(let i = 0; i < 10000; i++){
let li = document.createElement('li');
let text = document.createTextNode(i);
li.appendChild(text);
frg.appendChild(li); // 往虚拟标签中添加li
}
ul.appendChild(frg);
let clone = ul.cloneNode(true);
for(let i = 0; i < 10000; i++){
let li = document.createElement('li');
let text = document.createTextNode(i);
li.appendChild(text);
clone.appendChild(li); // 往克隆体中添加ul
}
ul.parentNode.replaceChild(clone, ul)
常见的优化性能的手段:
preload:告诉浏览器这个css资源在当前页面必须使用,应该立即加载和执行。浏览器会在HTML文档下载和解析完成之前加载这个资源。
prefetch:告诉浏览器这个css资源可能在未来的某个时间点用到,但不需要立即加载。浏览器会在空闲时间内异步加载这个资源,以便在需要时可以立即使用。
常见的性能指标:
怎样做性能监控?
跨域主要是因为浏览器的同源策略限制。同源是指两个页面拥有相同的协议(http/https)、主机(域名)和端口。
解决办法:
内存泄漏是指当程序不再需要某些对象时,没有释放这些对象所占用的内存,而导致内存占用持续增加,最终可能导致系统性能下降甚至崩溃。
常见的内存泄漏的原因及解决办法:
function outer(){
let a = '...(一个很大的对象)';
return function inner(){
console.log(a);
}
}
const run = outer();
//此时run不再使用,但是a也会保存在内存中。
const run = outer();
run(); // 正确释放 memory
setTimeout本质是延迟执行,只执行一次,而setInterval本质是定时执行,会照指定的时间间隔重复执行函数
setTimeout应用场景:动画效果的延迟,按钮防抖;setInterval应用场景:”轮播图的切换、时钟的更新等
const upload = setInterval(()=>{
console.log('upload');
},1000);
// 如果不再需要时没有 clearInterval(intervalId),intervalId 仍然保留在内存中
clearInteval(upload);
clearTimeout(timeoutId);
button.removeEventListener('click',clickfun);
const element = document.querySelector('#bnt1');
element.addEventListener('click',()=> {
//
});
//即使从DOM中移除element,其引用也会一直保存在内存中。
// 移除 DOM 元素时清理引用
function removeElement() {
element.removeEventListener('click', () => {
console.log('Button clicked');
});
element.parentNode.removeChild(element);
}
const map = new Map();
let obj = { key: 'value' };
map.set(obj, 'some data');
// 即使 obj 不再使用,map 仍然保留 obj 的引用,导致内存泄漏
obj = null; // 应该使用 map.delete(obj) 以确保 obj 可以被垃圾回收
const weakMap = new WeakMap();
(function() {
let obj = { key: 'value' };
weakMap.set(obj, 'some data');
// 当 obj 没有其他引用时,垃圾回收机制将自动释放它的内存
})();
// 在这种情况下,obj 不再存在于内存中,WeakMap 中的引用也会被垃圾回收
console.log(weakMap.has(obj)); // false,因为 obj 已被垃圾回收
// 内存泄漏示例
function createObjects() {
const obj1 = {};
const obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1;
}
createObjects();
// 解决内存泄漏
function createObjects() {
const obj1 = {};
const obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1;
// 不再需要 obj1 和 obj2 的引用时,将它们设为 null
obj1.ref = null;
obj2.ref = null;
}
createObjects();
// 或者使用 WeakMap 以避免内存泄漏
function createCyclicDependency() {
const a = {};
const b = { a };
a.b = b;
// 解除循环引用
delete a.b;
// 或者使用 WeakMap 以避免内存泄漏
const weakMap = new WeakMap();
weakMap.set(a, b);
}
createCyclicDependency();
let largeArray = new Array(1000000).fill('some data');
// 当 largeArray 不再需要时,显式地设置为 null
largeArray = null;
// 同样适用于大对象
let largeObject = { key1: 'value1', key2: 'value2', /* ... many more keys ... */ };
largeObject = null;
排查和预防内存泄漏:
引用计数:通过跟踪每个对象引用的次数来确定对象是否为垃圾。每个对象都有一个引用计数器,当一个对象被创建时,引用计数器初始化为1,当该对象被其他对象引用的时候,引用计数器+1,不再被其他对象引用的时候,计数器-1,当引用计数器减为0,就意味着该对象不再被引用,可以被垃圾收集器回收。
标记-清除:通过标记不再使用的对象,然后清除这些对象的内存空间,以便后续的内存分配引用。**标记阶段:**垃圾回收器会对内存中的所有对象进行遍历,从根对象开始递归地遍历对象的引用关系。对于每个被访问的对象,垃圾回收器会给它打上标记,表示该对象是可达的。这个过程确保了所有可达对象都会被标记。**清除阶段:**垃圾回收器会遍历整个内存,对于没有标记的对象,就被认为是垃圾对象,会立即收回,释放空间。可以处理循环引用
标记-整理:分为三个阶段:标记阶段、整理阶段和清除阶段。整理阶段:将内存中的活动对象移到一端使空闲空间连续,并且没有碎片化。
V8垃圾回收机制:分代收集和增量标记。新生代使用Scavenge算法,通常是采用Cheney算法,将内存分为两个半区,From区和To区,每次垃圾回收时,会将存活的对象复制到To区,并且清空From区,老生代使用标记整理算法。
缺点:如果本地的时间不准,则会出现资源无法缓存/资源永远被缓存的情况。
如果private和public都没有设置,则默认是private
last-modified:
缺一不可
ETag:从比较时间戳变成了文件指纹。文件指纹:根据文件内容计算的唯一哈希值,文件内容一旦改变,指纹就会改变。
总结:
强制缓存有cache-control和expires两种模式,cache-control是通过设置缓存持续时间来进行判断的,expires是通过设置时间戳来进行判断的。两者相斥,只能选择一个设置。能用cache-control不用expires
协商缓存有两种模式:last-modified和ETag,last-modified是通过设置文件的修改时间来进行判断,ETag是通过设置文件指纹进行判断的。两者没有谁好谁坏,根据业务场景选择。要设置cache-control:no-cache
返回304的都是协商缓存。
设计模式是针对软件设计中反复出现的问题所提出的通用解决方案。旨在提高代码的可复用性、可扩展性和可维护性。
分为三大类:
核心思想:是将对象的创建过程封装起来,让客户端不直接与具体的类进行交互,而是通过统一的接口来创建对象。
分为几种类型:
核心思想:确保一个类只有一个实例,并且提供一个全局访问点来获取该实例。
1.vue2是选项式API,Vue3是组合式API,能够更加灵活的服用和组合组件逻辑。
2.响应式系统的提升:使用Proxy代替Object.defineProperty,可监听新增删除属性以及数组的变化。
3.生命周期:用setup代替了vue2中的beforeCreate和Create生命周期。
4. diff算法重写:vue2通过标记静态根节点优化diff,Vue3 标记和提升所有静态根节点,diff的时候只需要对比动态节点内容。
5. vue3中支持多个template根节点
6. vuex,vue2创建实例使用new Store,vue3中使用createStore。
7. Route获取页面实例和路由信息:vue2用的是this获取route实例,vue3用useRoute和useRouter方法获取当前组件实例。
在 Vue 中,props 是父组件向子组件传递数据的一种方式。为确保传递的数据符合预期,Vue 提供了 props 的类型验证。在定义 props 时,可以指定其类型、是否必填、默认值等,来帮助开发者在调试时识别潜在的错误。
String
Number
Boolean
Array
Object
Function
Symbol
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
created:实例创建完成之后可以进行发送请求。适用于不依赖DOM的数据请求。
mounted:dom挂载之后发送请求,适用于需要使用DOM元素数据的请求或者组件在页面渲染后加载的数据。
前端单页路由
客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。
RouterLink 和 RouterView
vue3中使用creatRouter()进行创建。通过 useRouter() 和 useRoute() 来访问路由器实例和当前路由。
vue2中使用new Router进行创建。通过this.$router 和 this.$route获取。
pushState是压入浏览器的会话历史栈中,会使得history.length加1,而replaceState是替换当前的这条会话历史,因此不会增加history.length
怎么获取路由传参?
– 动态参数:类似/user/:123 这种,用useRoute获取实例,然后用router.params获取(vue2中用this.$route.params)
– 查询参数:类似/user ? id= 123,用useRoute获取实例,然后用router.query获取(vue2中用this.$route.query)
钩子函数
完整的导航解析流程
ref和reactive
RouterLink 是 Vue Router 提供的组件,用于在 Vue 应用中实现声明式的客户端路由跳转。它的作用类似于 <a> 标签,但不会触发页面刷新,而是使用 Vue Router 进行**单页面应用(SPA)**内的导航。
<template>
<RouterLink to="/home">跳转到首页</RouterLink>
</template>
//等价于
<a href="/home">跳转到首页</a>
主要 Props:
//字符串
<RouterLink to="/about">关于我们</RouterLink>
//对象
<RouterLink :to="{ path: '/about' }">关于我们</RouterLink>
//带query参数:访问的 URL 变成 product?id=123
<RouterLink :to="{ path: '/product', query: { id: 123 } }">商品详情</RouterLink>
<RouterLink to="/home" replace>跳转到首页(不记录历史)</RouterLink>
默认是 push,点击后可以用浏览器返回键回到上一个页面。
replace 方式不会在浏览历史中留下记录,点击后无法后退.
<RouterLink to="/profile" active-class="my-active-class">个人中心</RouterLink>
与 router.push 的区别
RouterLink 适用于模板中的导航链接
router.push 适用于 JavaScript 代码中动态跳转
this.$router.push('/about');
vue2 中v-for的优先级高于v-if,会优先渲染全部数据然后再判断v-if的条件,造成了性能的浪费。
vue3中v-if的优先级高于v-for,会优先进行v-if 的条件判断,然后再进行v-for渲染。如果v-if有依赖v-for的变量,就会发生报错。
Transition:会在一个元素或组件进入和离开 DOM 时应用动画。
TransitionGroup:用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。
keepAlive:它的功能是在多个组件间动态切换时缓存被移除的组件实例。
Teleport:它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
Suspense:用来在组件树中协调对异步依赖的处理。
keepAlive:官方文档
可使用场景:
<script setup>
import Home from './Home.vue'
import Posts from './Posts.vue'
import Archive from './Archive.vue'
import { ref } from 'vue'
const currentTab = ref('Home')
const tabs = {
Home,
Posts,
Archive
}
</script>
<template>
<div class="demo">
<button
v-for="(_, tab) in tabs"
:key="tab"
:class="['tab-button', { active: currentTab === tab }]"
@click="currentTab = tab"
>
{{ tab }}
</button>
<component :is="tabs[currentTab]" class="tab"></component>
</div>
</template>
效果地址:
效果地址
<KeepAlive> 默认会缓存内部的所有组件实例,我们可以通过includes和exclude prop来定制该行为。
max 来限制可被缓存的最大组件实例数。
生命周期:OnActivated()和OnDeactivated()注册相应的两个状态生命周期钩子。
onActivated 在组件挂载时也会调用,并且 onDeactivated 在组件卸载时也会调用。
这两个钩子不仅适用于 <KeepAlive> 缓存的根组件,也适用于缓存树中的后代组件。
本文发布于:2025-04-06 10:29:00,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/1743906572584599.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |