前端面试实录,(回答均为个人见解)

面试题

js

1. 箭头函数

箭头函数和普通函数的区别是:

  1. 没有自己的this,它内部的this使用的是上层函数作用域或者全局的this
  2. 返回值有隐式的返回和显示的返回两者
  3. 没有arguments,需要使用...args的方式获取形参列表
  4. 没有prototype,所以不能使用new关键字。也不可以使用call等方法改变this的指向
javascript 复制代码
let obj = {
	fn: () => {
		console.log(this)
	}
}
obj.fn() // window
javascript 复制代码
let obj = {
	fn: () => 123 // 隐式的返回
}
console.log(obj.fn())
2. let 和 var 的区别

let和var都是js中用于声明变量的关键字,他们的区别在于:

  1. let 有块级作用域的概念,var只有函数作用域或者全局作用域的概念

    javascript 复制代码
    {
    	let a = 100
    	var b = 200
    }
    console.log(b)
    console.log(a)
  2. var有变量提升,在变量声明前使用,值为undefined。

  3. let 在同一作用域内,不可以重复声明相同名字的变量

3. new关键字在new的时候做了些什么

实现new关键字

javascript 复制代码
// 模拟new关键字,创建构造函数

function Person(name,age) {
	this.name = name;
	this.age = age;
}

function createInstance(contrustor,...args) {
	// 1. 创建一个新的对象
	let newObj = {}
	// 2. 设置原型 将新对象的隐式原型,指向显示原型
	newObj.__proto = contrustor.prototype
	// 3. 改变构造函数的this指向
	let result = contrustor.apply(newObj,args)
	// 4. 如果是对象类型就返回,不是就返回新创建的对象
	let reObj = (typeof result === 'object' && result !== null) ? result : newObj
	return reObj
}

let person = createInstance(Person,'jjs',14)
console.log(person.name)

那么我们可以发现如果构造函数有返回值,且为对象时那么new表达式会返回这个对象,而不是新创建的对象。这允许构造函数在特定情况下覆盖默认的实例化行为。

也就是

javascript 复制代码
// 模拟new关键字,创建构造函数

function Person(name,age) {
	this.name = name;
	this.age = age;
	return {
		a: 1
	}
}

function createInstance(contrustor,...args) {
	// 1. 创建一个新的对象
	let newObj = {}
	// 2. 设置原型 将新对象的隐式原型,指向显示原型
	newObj.__proto = contrustor.prototype
	// 3. 改变构造函数的this指向
	let result = contrustor.apply(newObj,args)
	// 4. 如果是对象类型就返回,不是就返回新创建的对象
	let reObj = (typeof result === 'object' && result !== null) ? result : newObj
	return reObj
}

let person = createInstance(Person,'jjs',14)
let person2 = new Person('jtt',18)
console.log(person.name,person.a)
console.log(person2.name,person2.a)

这种情况下,只读的到返回的对象

4. call,apply和bind的区别

他们的作用是,改变this的指向

区别是:

call: func.call(thisArg, arg1, arg2, ...),第一个参数为要指定的this,以分散的形式将参数传入

上面那个例子,我们要使用call的话:

let result = contrustor.call(newObj,...args)

apply :方法调用一个函数,其具有一个指定的this值,以及以一个数组(或类数组对象)的形式提供的参数

bind: 形式和call相同 func.bind(thisArg, arg1, arg2, ...),第一个参数为要指定的this,以分散的形式将参数传入

区别是:callapply都是直接调用 bind则是用于创建一个新的函数,这个新函数被bind调用时的this被永久绑定,之后无论这个新函数如何被调用,this都不会改变。

5. localStorage,sessionStorage cookie和session的区别
  1. 存储位置和生命周期

    localStorage,sessionStorage cookie存储在客户端,也就是浏览器上面。session存在服务器上面

    localStorage,持久化存储。sessionStorage,仅在当前会话页面有效,页面关闭sessionStorage就会被删除

    cookie 根据设置的过期时间而定,如果没有设置,那么浏览器关闭,cookie删除

    session 受到服务器的超时时间的影响

  2. 存储的内容大小

    localStorage,sessionStorage 存储空间较大,cookie存储空间较小一般为4kb,session不占用客户端内存,与服务端存储空间相关

6. js创建对象的几种方式
  1. 使用字面量的方式

    let obj = {}

  2. 使用Object.create() 静态方法以一个现有对象作为原型,创建一个新对象。

    需要一个参数,构造函数。相当于newObj.__porto = Fn.prototype

    javascript 复制代码
    var personProto = {  
        greet: function() {  
            console.log("Hello, my name is " + this.firstName + " " + this.lastName);  
        }  
    };  
      
    var person = Object.create(personProto);  
    person.firstName = "John";  
    person.lastName = "Doe";  
      
    person.greet(); // 输出: Hello, my name is John Doe
  3. 构造函数,使用new 关键字来创建对象

  4. 工厂函数,一个函数的返回值为对象,然后就可以通过调用这个函数来批量的产生对象。

    javascript 复制代码
    function createPerson(firstName, lastName) {  
        var obj = {};  
        obj.firstName = firstName;  
        obj.lastName = lastName;  
        obj.greet = function() {  
            console.log("Hello, my name is " + this.firstName + " " + this.lastName);  
        };  
        return obj;  
    }  
      
    var person = createPerson("John", "Doe");  
    person.greet(); // 输出: Hello, my name is John Doe
  5. 通过new Obejct的方式

  6. 通过class的方式

7.this的指向

有三种情况

  1. 作为对象的属性调用,如果不是箭头函数,那么this指向调用的那个对象
  2. 在函数当中:普通函数,非严格模式下是window或者golab,严格模式下是undefined
  3. 构造函数中,是实例对象

闭包

在什么时候产生,在什么时候死亡

闭包就是,内部函数引用到了外部函数的变量,导致外部函数空间不能被释放

在内部函数创建时产生,在内部函数销毁时闭包死亡

8. 继承
  1. 可以通过原型链继承

    Child._proto _= Parent.prototype

    Child.prototype.constructor = Child

    案例:

    这样的话,只能继承的到原型上面的方法,不能动态的去指定属性的值

    javascript 复制代码
    function Parent() {  
        this.name = 'Parent';  
    }  
      
    Parent.prototype.sayName = function() {  
        console.log(this.name);  
    };  
      
    function Child() {  
        this.age = 10;  
    }  
      
    // 继承Parent  
    Child.prototype = Object.create(Parent.prototype);  
    Child.prototype.constructor = Child;  
      
    var child = new Child();  
    child.sayName(); // 输出: Parent
  2. 构造函数继承

    通过new的方式

  3. 组合继承,将借用构造函数和原型链继承结合起来

    javascript 复制代码
    function Parent(name) {  
        this.name = name;  
    }  
      
    Parent.prototype.sayName = function() {  
        console.log(this.name);  
    };  
      
    function Child(name,age) {
    	Parent.call(this,name)
        this.age = age;  
    }  
      
    // 继承Parent  
    Child.prototype = new Parent()
    Child.prototype.constructor = Child;  
      
    let child = new Child("jjs",20); 
    let child2 = new Child("jtt",18);
    child2.sayName(); // 输出: Parent
9. 什么是事件循环机制

用于协调异步任务的顺序,传递信息以及处理用户交互。

由调用栈,执行队列,事件循环,三部分组成。

当主线程的同步代码执行完毕后,事件循环会开始工作。它首先检查微任务队列,如果有微任务,则依次执行微任务队列中的所有任务,直到微任务队列为空。然后,事件循环会从宏任务队列中取出第一个宏任务执行。每个宏任务执行完毕后,会再次清空微任务队列,并继续执行下一个宏任务,如此循环往复。

node的事件循环与浏览器上面的事件循环有什么区别

  1. 实现方式不同

    node.js : 主要是处理i/o操作和网络请求,基于Libuv库利用底层操作系统的多线程特性去实现。

    浏览器:主要处理,事件,用户的交互。单线程的,通过异步回调和触发事件来进行异步操作

  2. 宏任务和微任务的处理

    node.js : 宏任务包括整体的代码、setTimeout、setInterval、I/O操作等,微任务则包括Promise的回调和process.nextTick() 先执行宏任务,清空当前微任务队列。执行下一次tick

    浏览器:浏览器的宏任务同样包括setTimeout、setInterval、DOM操作、AJAX请求等,但微任务则包括Promise的回调、MutationObserver以及queueMicrotask等,先执行微任务再执行宏任务

10. Promise.all()、Promise.race()的区别

promise有三种状态

  1. Pending(等待中):初始状态,既不是成功,也不是失败状态。
  2. Fulfilled(已成功):意味着操作成功完成。
  3. Rejected(已失败):意味着操作失败。

基本用法:

javascript 复制代码
let promise = new Promise(function(resolve, reject) {  
  // 异步操作  
  if (/* 异步操作成功 */) {  
    resolve(value); // 将Promise的状态从"pending"变为"fulfilled",并将异步操作的结果,作为参数传递出去  
  } else {  
    reject(error); // 将Promise的状态从"pending"变为"rejected",并将错误作为参数传递出去  
  }  
});  
  
// 处理Promise的结果  
promise.then(function(value) {  
  // 成功时调用  
  console.log(value);  
}).catch(function(error) {  
  // 失败时调用  
  console.log(error);  
});

Promise.race方法接受多个promise,返回最快成功的一个结果

Promise.all 方法接受一个数组,里面的promise都成功则为成功,有一个失败就都不成功

11. 怎么判断一个变量的类型为null
  1. 使用====

    let value = null;

    if(value === null) {console.log("为null")}

  2. 使用原型

    let value = null;

    if(Obejct.prototype.toString.call(value) == [object null]) {console.log("为null")}

  3. 使用es6

    let value = null;

    if(Object.is(value)) {console.log("为null")}

    使用typeof可以确定哪些变量的类型

    undefined,number,string,Boolean,

12.实现图片懒加载

使用IntersectionObserver这个api就可以轻松的实现它

官方文档:IntersectionObserver.root - Web API | MDN (mozilla.org)

提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(root)。

实例属性(配置项):

root 属性用来获取当前 intersectionObserver 实例的根元素。

rootMargin 属性 可以理解为,懒加载的预加载,比如图片的懒加载,不是等图片元素进入可视区域之后,才去加载,而是检测到,离进入可视区域,在一定范围内部的时候,就提前加载(叫做预加载吧)。

threshold: 1.0, 阈值为 1.0 意味着目标元素完全出现在 root 选项指定的元素中可见时,回调函数将会被执行。

案例:

javascript 复制代码
let options = {
	root:null, // 设置为null,顶层视口
	rootMargin: '0px', // 距离视口多少时显示
	threshold: 1.0 // 标元素完全出现在 root 选项指定的元素中可见
}
function callback(entries) {
	for (let entrie of entries) {
		if(entrie.isIntersecting) {
			let img = entrie.target // 将dom元素存放到了target属性上面
			img.src = "./img/test.gif"
		}
	}
}

let ob = new IntersectionObserver(callback,options)

let data = document.querySelectorAll('img')
data.forEach(item => {
	ob.observe(item)
})

自定义指令的形式

vue 复制代码
<script setup generic="T" lang="ts">
import {useRouter} from "vue-router";
import {Directive} from "vue";
import defaultImg from "../assets/image/vue.svg";

const router = useRouter()

const vLazy: Directive =(el, binding) => {
  let ob = new IntersectionObserver((entries) => {
    for (const entry of entries) {
      if(entry.isIntersecting) {
        let imgDom:HTMLImageElement = entry.target as HTMLImageElement
        import(binding.value).then(res => {
          imgDom.src = res.default
          ob.unobserve(el)
        })
      }
    }
  },{
    threshold: 1
  })
  ob.observe(el)
}
</script>

<template>
<div>
  <h1>我是b组件</h1>
  <button @click="router.back()">返回</button>
  <hr>
  <img :src="defaultImg" v-lazy="'../assets/1.png'">
  <img :src="defaultImg" v-lazy="'../assets/2.png'">
  <img :src="defaultImg" v-lazy="'../assets/3.png'">
</div>
</template>

<style scoped>
img {
  width: 200px;
  display: block;
}
</style>
13 深浅拷贝
  1. 浅拷贝,只复制了引用,没有复制值

    javascript 复制代码
    let arr = [1,2,3]
    let arr2 = arr
    arr[1] = 10
    console.log(arr2)
    let obj = {
        name: 'jjs'
    }
    let obj2 = Object.assign(obj)
  2. 深拷贝是复制真正的值

    javascript 复制代码
    // 使用JSON.parse,JSON.stringify()
    let obj = {
        a: 1,
        b: 3
    }
    let obj1 = JSON.parse(JSON.stringify(obj))
    // 使用递归的方式
    function deepClone(obj) {
        let newObj = obj instanceof Array ? [] : {}
        for (let key in obj) {
            if(obj[key] && typeof obj[key] === 'object') {
                newObj[key] = deepClone(obj[key])
            }else {
                newObj[key] = obj[key]
            }
        }
        return newObj
    }
    let obj2 = deepClone(obj)
14. script标签加什么属性可以变为异步加载

​ 可以使用async和defer两个属性

​ 不同的是:

​ 使用defer属性的脚本会等到整个文档被解析完成后,再按照它们在文档中出现的顺序执行

​ 使用async脚本将独立于页面的其他部分异步下载,并且一旦下载完成,浏览器就会暂停解析HTML文档来执行这个脚本不会按照它们在页面上出现的顺序执行

css

1. 如何快速实现居中

(1)给父元素添加display: flex;,目标元素: margin: auto;

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				padding: 0;
				margin: 0;
			}
			.container {
				width: 100vw;
				height: 100vh;
				display: flex;
			}
			.content {
				width: 200px;
				height: 200px;
				background-color: aquamarine;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="content">
				
			</div>
		</div>
	</body>
</html>

​ (2) 给父元素 display: flex;justify-content: center;align-items: center;

css 复制代码
.container {
	width: 100vw;
	height: 100vh;
	display: flex;
	justify-content: center;
	align-items: center;
}
.content {
	width: 200px;
	height: 200px;
	background-color: aquamarine;
}

​ (3)利用position进行定位

css 复制代码
*{
	padding: 0;
	margin: 0;
}
.container {
	width: 100vw;
	height: 100vh;
	position: relative;
}
.content {
	width: 200px;
	height: 200px;
	background-color: aquamarine;
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%,-50%);
}
2. margin和padding有什么不同

​ margin 是☞,边框与外部元素之间的距离,即元素与其他元素之间的距离,不会影响到元素内部

​ padding 是☞, 边框与内容区的一个距离,它作用于元素本身,影响元素内部的空间

​ 怪异盒子模型:

​ 在怪异盒子模型中,高度和宽度是指的总高度和总宽度。如果设置了高宽为100,再设置边框为10px,padding为20px,那么内容区就只剩70px

​ 开启怪异盒模型: box-sizing: border-box;

css 复制代码
.content {
	width: 200px;
	height: 200px;
	background-color: aquamarine;
	box-sizing: border-box;
	padding: 20px;
	border: 3px #bfa solid;
}
3. vw和百分比的区别

​ vw是相对于,视口的宽度进行计算,百分比则是相对于父元素的宽度进行计算

4. 如何让字体变的更小

​ (1)transform: scale(.8);

​ (2)利用rem,em来进行让字体相对于元素变换

​ rem: 相对于根元素进行计算

​ em: 相对于父元素进行计算

css 复制代码
*{
	padding: 0;
	margin: 0;
}
html {
	font-size: 20px;
}
.container {
	width: 100vw;
	height: 100vh;
	position: relative;
}
.content {
	width: 200px;
	height: 200px;
	box-sizing: border-box;
	padding: 20px;
	border: 3px #bfa solid;
	font-size: 30px;
}
.content>:nth-child(1) {
	font-size: .5rem;
}
.content>:nth-child(2) {
	font-size: .5em
}
5.回流与重绘

​ 回流就是:改变了dom的几何结构,浏览器需要对页面的位置分布重新进行计算并进行绘制

​ 导致回流的原因:页面第一次渲染,元素尺寸发生变化,字体大小发生变化,删除或者新增dom

​ 重绘就是:改变了dom的样式而没有改变dom的几何结构,比如:背景颜色等,那么浏览器就会为该元素重新绘制

​ 导致重绘的原因:visibility属性被修改,样式发生变化

visibility

​ 作用:控制元素是否可见,有三个值:visible,可见,hidden:不可见但依然占据空间,collapse:不可见也不占据空间

visibility和display的区别

​ 使用display:none;之后元素并不可见也不占用空间,如果想要不可见但依然占据空间还是要使用visibility:hidden;

​ 减少回流与重绘:

​ 合并dom操作,可以搞一个异步的队列,将多次dom操作统一执行

6.overflow

​ 用于指定内容超出大小后,浏览器如何去处理溢出的内容。

​ 他一共有四个属性:分别是hidden,auto,scroll,visible,他们分别的功能是:

​ visible: 默认值,不管溢出。设置和没设置一样

​ hidden:直接裁掉溢出的部分,那么如果是下面还有内容的话,也会一起被裁掉

​ auto: 如果内容溢出,则浏览器会显示滚动条以便查看其余的内容。如果内容没有溢出,则不显示滚动条

​ scroll: 不管有没有溢出,都会显示滚动条。没有溢出的话滚动条是失活的。

css 复制代码
.content {
	width: 200px;
	height: 200px;
	box-sizing: border-box;
	padding: 20px;
	border: 3px #bfa solid;
	font-size: 30px;
	overflow: auto;
}
.content>:nth-child(1) {
	font-size: .5rem;
	height: 300px;
}
.content>:nth-child(2) {
	font-size: .5em
}
/**
	这里出现了元素溢出,然后就会出现滚动条,下拉就可以看到,第二个子元素的内容
*/
7.position

​ 它用于控制元素再页面上的定位方式

​ 有五个属性值,分别是static,relative,absolute,fixed,sticky他们的功能是

​ static:静态定位,默认值,按正常文档流排序

​ relative:相对定位,相对于其在普通流中的父元素进行定位,可以使用left,top,bottom,right进行调位置

​ absolute: 绝对定位, 相对于最近的开启了position且值不为static的元素进行定位。会脱离文档流

​ fixed:固定定位,相对于浏览器的窗口进行定位,无论页面如何滑动,该元素都会保持在相同的位置

css 复制代码
*{
	padding: 0;
	margin: 0;
}
html {
	font-size: 20px;
}
.container {
	width: 100%;
	height: 100%;
	position: relative;
}
.content {
	width: 200px;
	height: 200px;
	box-sizing: border-box;
	padding: 20px;
	border: 3px #bfa solid;
	font-size: 30px;
	position: fixed;
	top: 0;
}
.content>:nth-child(1) {
	font-size: .5rem;
}
.content>:nth-child(2) {
	font-size: .5em
}
.longer {
	height: 1300px;
	background-color: whitesmoke;
}
html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" href="./style.css">
	</head>
	<body>
		<div class="container">
			<div class="content">
				<p>我是相对于html的字体</p>
				<p>我是相对于父元素字体</p>
			</div>
			<div class="longer"></div>
		</div>
	</body>
</html>

​ sticky: 粘滞定位,是一种特殊的定位方式,它结合了相对定位和固定定位的特点,粘性定位的元素在滚动到一定位置之前表现为相对定位,即元素按照正常文档流进行排列;当页面滚动到特定位置时,元素会"粘"在指定位置,表现为固定定位

修改一下即可看到效果:

css 复制代码
position: sticky;
top: 0px;
8. float

​ 浮动布局,允许一个元素脱离文档流,向左或者向右浮动

​ 主要有三个属性值:none,left ,right

​ 三个属性值的作用是设置不浮动向右或者向左浮动

css 复制代码
*{
	padding: 0;
	margin: 0;
}
html {
	font-size: 20px;
}
.container {
	border: 2px solid skyblue;
	padding: 5px;
}
.content {
	width: 200px;
	height: 200px;
	background-color: aquamarine;
	float: left;
}
html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" href="./style.css">
	</head>
	<body>
		<div class="container">
			<div class="content">
				
			</div>
		</div>
	</body>
</html>

这样的话,就开启了浮动,但是也带了一个问题,就是高度塌陷

所以就需要清除浮动所带来的影响,三种解决,1. 使用伪类。2. 父元素一起浮动,3. 开启bfc

什么是bfc

​ bfc是一个独立的渲染环境,在计算高度时,也会计算浮动元素的高度,所以就解决了高度塌陷的问题

​ 在同一个bfc的元素外边距会重叠,可以触发不同的bfc去计算,解决外边距重叠的问题

​ 主要作用就是解决上下外边距重叠和清楚浮动所带来的影响

css 复制代码
*{
	padding: 0;
	margin: 0;
}
html {
	font-size: 20px;
}
.container {
	border: 2px solid skyblue;
	overflow: hidden; /* 触发bfc */
	padding: 5px;
}
.content {
	width: 200px;
	height: 200px;
	background-color: aquamarine;
	float: left;
}

vue

1. 什么是单向数据流

在 Vue 中,数据流主要遵循一个父到子的方向。父组件通过 props 向子组件传递数据,而子组件不能直接修改通过 props 接收的数据。如果子组件需要基于接收到的数据做一些修改,它应该通过事件(如自定义事件)来通知父组件进行更改,然后由父组件来决定是否更新数据

案例:

vue 复制代码
<script setup lang="ts">
import BaseRefAndReactive from "./components/BaseRefAndReactive.vue";
import {ref} from "vue";
const list = ref([1,2,3,4,5])
const handleClick = (name:string,...args) => {
  console.log(name,"父------>")
  console.log(args)
}
</script>
 
<template>
 
 <BaseRefAndReactive title="这是标题" :list="list" @on-click="handleClick"></BaseRefAndReactive>
</template>
 
<style scoped>
 
</style>
vue 复制代码
<script setup lang="ts">
withDefaults(defineProps<{
  title: string,
  list: number[]
}>(), {
  title: 'default title',
  list: () => [1,2,3]
})
let emit = defineEmits(["on-click"])
const handleClick = () => {
    emit("on-click", "我是子组件1",123,"as",{name:"张三"})
}
</script>
 
<template>
  <div>
    <h1>{{ title }}</h1>
    <ul>
      <li v-for="(item,index) in list" :key="index">{{ item }}</li>
    </ul>
    <button @click="handleClick">传值</button>
  </div>
</template>
 
<style scoped>
 
</style>
2. vue router如何进行传参

提供了两种方式进行传参

  1. query

    查询参数是通过URL的查询字符串来传递的,它们会被附加在URL的?后面,并以&分隔。这种方式适合非敏感数据的传递,如搜索词等。

    query必须要是一个对象

    javascript 复制代码
    import {useRouter} from 'vue-router'
    const router = useRouter()
    router.push({ path: '/foo', query: { userId: 123 }})  
    // 结果的URL将会是 /foo?userId=123

    接受参数

    javascript 复制代码
    import {useRoute} from 'vue-router'
    const route = useRoute()
    created() {  
      // 访问查询参数  
      console.log(route.query.userId) // 输出:123  
    }
  2. 动态路由匹配

    当路由路径中包含动态片段时,如/user/:id,可以通过params来传递参数,但注意,这种方式与query不同,它不会在URL中直接显示参数。它通常与路由的嵌套或命名视图一起使用,并通过name来指定路由,然后使用params来传递参数。

    使用params必须使用name的形式,使用path的形式不可以

    javascript 复制代码
    import {useRouter} from 'vue-router'
    import {ref} from 'vue'
    const userID = ref(1)
    function toDetails (item:Data) {
      router.push({
        name: "B",
        params: {
          id: userID
        }
      })
    }

    获取:

    javascript 复制代码
    import {useRoute} from 'vue-router'
    const route = useRoute()
    created() {  
      // 访问查询参数  
      console.log(route.params.userID) // 输出:1  
    }
  3. 两者的区别

    query 传参配置的是 path,而 params 传参配置的是name,在 params中配置 path 无效

    query 在路由配置不需要设置参数,而 params 必须设置

    query 传递的参数会显示在地址栏中

    params传参刷新会无效,但是 query 会保存传递过来的值,刷新不变 ;

3. vue-router hash模式和history模式的区别
  1. url的区别

    hash模式:http://localhost:3000/#/router

    会包含一个#,#后面是路由的路径

    history模式:http://localhost:3000/router

    不包含#,端口号后面既是路由的路径

  2. 实现的方式不同

    hash模式:原理是 HTML5 的 window.location.hash 属性,这个属性值的改变(即 URL 中 # 后面的部分)不会导致页面重新加载

    history模式:利用了 HTML5 History API 来实现 URL 的跳转而不重新加载页面

4. vuex

Vuex是一个状态管理模式和库,用于集中式存储管理Vue.js应用中的所有组件的状态

有五个核心api

  1. state,是Vuex中的基本数据对象,用于存储应用的状态,它类似于组件的data属性
  2. getters:类似于组件的计算属性,可以利用state中的值,计算出新的值
  3. mutations:用于修改state里面的数据,必须是同步的函数,通过commit方法调用mutations
  4. actions:,可以执行异步操作(如API调用),并在操作完成后通过commit方法调用mutations来修改stat
  5. Modules:Vuex允许我们将store分割成模块(modules)。每个模块拥有自己的state、mutations、actions和getters等
5. public文件夹下的文件和src下的assert文件夹下的文件有什么区别

​ public文件夹下的文件在打包的时候不会被打包,直接放在根目录下,可以直接去访问,assert文件夹里的文件会随着src文件夹一起打包。

typescript

1. type和interface的区别
  1. 使用场景的不同

    • Type Aliases (type) 通常用于简单的类型定义,如字面量类型、联合类型、元组等。
    • Interfaces (interface) 更适合定义对象的形状,尤其是当对象包含方法时。同时,由于支持继承,它更适合构建复杂、可扩展的类型系统。
  2. 声明合并

    interface,同名的话,会将两个同名的interface进行合并而type却不可以

相关推荐
y先森14 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy15 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891118 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端