1.vuex:store{state, mutations, actions, getters,modules};解决跨组件通信、数据集中式存储
①state用于存储共享数据,mutation用于修改store数据;
state调用方式
1). this.$store.state;
2) ...mapState(['count'])使用方式为this.count
②mutations用于同步修改state属性调用方式
1) this.$store.commit('func',params);
2) 在methods中调用...mapMutations(['mutation'])使用方式为this.func()
③actions用于处理异步任务调用mutation来间接修改state数据、使用方式为
1) this.$store.dispatch('mutation');
2) 在methods中调用...mapActions(['action']) 使用this.action()
④getters用于包装state值用法类似vue的filters其调用方式为
1) this.$store.getters.getter;
2) ...mapGetters(['getter'])
⑤modules将store拆分成多个模块,模块化状态管理
2.双向数据绑定:通过数据劫持结合发布者-订阅者模式来实现,通过Object.defineProperty()的get和set来实现数据劫持
3.跨域:
① CORS :对方服务端设置响应头 ”Access-Control-Allow-Origin“,CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。
② 服务端代理: 在浏览器客户端不能跨域访问,而服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就没有跨越问题。简单地说,就是浏览器不能跨域,后台服务器可以跨域。(一种是通过http-proxy-middleware插件设置后端代理;另一种是通过使用http模块发出请求)
③ JSONP :回调函数+数据就是 JSON With Padding,简单、易部署。(做法:动态插入script标签,设置其src属性指向提供JSONP服务的URL地址,查询字符串中加入 callback 指定回调函数,返回的 JSON 被包裹在回调函数中以字符串的形式被返回,需将script标签插入body底部)。缺点是只支持GET,不支持POST(原因是通过地址栏传参所以只能使用GET)
④ postMessage:HTML5的postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。适用于不同窗口iframe之间的跨域
⑤ document.domain 跨子域:( 例如a.qq.com嵌套一个b.qq.com的iframe ,如果a.qq.com设置document.domain为qq.com 。b.qq.com设置document.domain为qq.com, 那么他俩就能互相通信了,不受跨域限制了。 注意:只能跨子域)
4.对VUE的理解:vue是一个构建用户界面的渐进式js框架,是一个mvvm框架也就是数据双向绑定,通过尽可能简单的API时间响应的数据绑定和组合的视图组件。
5.父子组件之间互相传值
① props,$emit
② $refs
③ $parent,$children
④ 定义全局事件window.eventBus = new Vue();通过$emit和$on来传递数据
⑤ vuex
⑥ 父组件provide定义数据/子组件inject注入数据
⑦ 混入mixins
6.Vue中父子组件的生命周期执行顺序?
7.性能优化:减少IO、代码压缩、减少网络请求;静态资源缓存;减少DOM操作、异步加载;DNS预解析
8.页面卡顿的原因:
① JS线程长时间占用:浏览器包括js线程和GUI线程,而二者是互斥的,当长时间占用js线程时,会导致渲染不及时,出现页面卡顿
② 简化DOM结构:当DOM结构越复杂时,需要重绘的元素也就越多
③ 资源加载阻塞:js资源放在body之前;行内script阻塞;css加载会阻塞DOM树渲染;资源过大阻塞
④ 内存泄漏导致内存过大
9.内存泄漏:
① 意外的全局变量
② 闭包
③ 被遗忘的计时器
④ DOM删除或清空时,事件未清除
10.ES6新特性:
① 变量声明let和const:块级作用域,不能重复声明,let不具备变量提升
② 模板字符串使用反引号,引用变量使用${}
③ 箭头函数:省略function、单行内容可省略return、单个参数可省略()、this指向继承上下文的this指向
④ 函数参数可设置默认值
⑤ Spread合并数组/Rest析构数组
⑥ 对象和数组解构
⑦ 超类super
⑧ for...in和for...of
⑨ class类 默认有一个构造函数constructor
11.HTTP与HTTPS的区别:
① HTTP 明文传输,数据未加密,安全性差,HTTPS(SSL+HTTP) 数据传输加密,安全性好
② HTTP 页面响应速度比 HTTPS 快
③ 端口不同
④ HTTPS 比 HTTP 要更耗费服务器资源
12.GET与POST的区别:
① get获取数据、post发送数据
② get通过url传递数据、post数据放在from数据体内提交用户不可见
③ get请求有长度限制、post请求对数据长度没要求
④ get会被缓存而post不会
⑤ get请求会被保留记录、post不会保留记录
⑥ post比get更安全
⑦ get只允许ASCII字符、post没有限制也允许二进制
⑧ GET和POST最大的区别主要是GET请求是幂等性的,POST请求不是。(幂等性:对同一URL的多个请求应该返回同样的结果。)因为get请求是幂等的,在网络不好的隧道中会尝试重试。如果用get请求增数据,会有重复操作的风险,而这种重复操作可能会导致副作用
13.HTTP请求方法:
GET 向服务器获取数据
POST 向服务器发送数据
HEAD 与 GET 相同,但只返回 HTTP 报头,不返回文档主体。
PUT 上传指定的 URI 表示。
DELETE 删除指定资源。
OPTIONS 返回服务器支持的 HTTP 方法。
CONNECT 把请求连接转换到透明的 TCP/IP 通道。
14.宏任务(macrotask )和微任务(microtask ):
宏任务:
1)宏任务是 JavaScript 中较大的任务,它们通常代表着整个执行的较大单元。
2)宏任务是由 JavaScript 的事件循环机制安排执行的,每次事件循环(Event Loop)会检查并执行一个宏任务队列中的任务。
3)属于宏任务的有:script (可以理解为外层同步代码)、setTimeout/setInterval、UI rendering/UI事件、postMessage、MessageChannel、setImmediate、I/O(Node.js)
微任务:
1)微任务是 JavaScript 中较小的任务,通常是用于处理一些需要立即执行的任务。
2)微任务的执行优先级高于宏任务。每次执行完一个宏任务后,事件循环会立即执行所有的微任务,然后才会去执行下一个宏任务。微任务是事件循环机制的一部分,它保证了某些任务会在其他任务之前执行。
3)属于微任务的有:Promise.then、MutaionObserver、Object.observe(已废弃;Proxy 对象替代)、process.nextTick(Node.js)
执行顺序:同步任务>process.nextTick>微任务>宏任务>setImmediate
事件循环:
15.vue权限控制:
① 接口权限:通过axios对请求拦截将登录时获取到的token带入请求头;如果返回token失效或错误请求则跳转到登录界面
② 路由权限:
1)初始化即挂载全部路由,每次路由跳转前做校验。路由过多时性能不好。
2)初始化时先挂载不需要权限控制的路由,比如登录页面,404页面,如果用户通过url强制访问,则会进入404,登录后,获取用户权限信息,然后筛选有权限访问的路由,在全局路由守卫里进行调用addRoutes添加路由
16.css3有哪些更新?
① box-sizing:border-box;
② 新增属性选择器:
1)元素[属性^=值]: 选择以指定字符开头的属性值的元素
2)元素[属性$=值]: 选择以指定字符结尾的属性值的元素
③ 新增伪类选择器:
:root 可以理解为根
li:first-child 代表找出父元素中第一个li子元素
li:last-child 代表找出父元素中最后一个li子元素
li:nth-child(n) 找出父元素中的第n个li子元素
li:nth-child(even) 代表找出父元素中奇数的li子元素
li:nth-child(odd) 代表找出父元素中偶数的li子元素
li:empty 代表找出父元素中li子元素内容为空的标签
li:nth-of-type(n) 找出li标签中第几个
li:first-of-type 找出li标签中第一个
li:last-of-type 找出li标签中最后一个
li:only-child 唯一子元素
④ 2d变换效果:transform:值
transform:translate(值1,值2); |移动
transform:rotate(角度);transform-origin:横向坐标 纵向坐标; |旋转
transform:scale(值); |缩放
⑤ 过渡效果:
transition:动画css属性 过渡时间秒数 速度类型 延迟的秒数
17.实现旋转有哪些方法?
Canvas rotate:
let c = canvas.getContext("2d");
c.rotate(90 * Math.PI / 180);
c.drawImage(img, 0, -img.height);
CSS3:
transform: transform: rotate(90deg);
18.flex:1是什么意思? (代表均匀分配元素)
flex-grow: 1; (用来“瓜分”父项的“剩余空间”)当父元素的宽度大于所有子元素的宽度的和时(即父元素会有剩余空间),子元素如何索取分配父元素的剩余空间。值越大,索取的越厉害。
flex-shrink: 1; (“吸收”超出的空间)父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。值越大,减小的越厉害。
flex-basis: 0%; (设置子项的占用空间)该属性用来设置元素的宽度,其实,width也可以设置宽度。如果元素上同时设置了width和flex-basis,那么width 的值就会被flex-basis覆盖掉。
19.this指向有哪几种?
① 作为函数调用,非严格模式下,this指向window,严格模式下,this指向undefined;
② 作为某对象的方法调用,this通常指向调用的对象。
③ 使用apply、call、bind 可以绑定this的指向。
④ 在构造函数中,this指向新创建的对象
⑤ 箭头函数没有单独的this值,this在箭头函数创建时确定,它与声明所在的上下文相同。
20.对比一下for、for..in、for..of、foreach、map的区别、返回值是什么?
① for…in以原始插入顺序访问对象的可枚举属性,包括从原型继承而来的可枚举属性
② for…of(根据值遍历): 在可迭代对象(Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,正确响应break,continue,return语句
③ forEach:只能遍历数组,不能中断,没有返回值
④ map(根据index遍历):只能对元素进行加工处理,产生一个新的数组对象
⑤ for: 常规语句遍历,可循环数字,字符串,数组
21.数组方法forEach、map、filter、sort的用法?
① forEach: 多用于对数组自身的改变和各元素相关统计性的计算
② map: 新建一个数组,需要有承载对象,将不改变原数组
③ filter: 对数组过滤,返回过滤数据
④ sort: 对数组的元素进行排序
22.promise、async\await、setTimeout三个有什么区别?
① Promise 是一种表示异步操作最终完成(或失败)并返回结果的对象。它提供了 .then() 和 .catch() 方法来处理成功和失败的结果。 Promise 使得异步操作可以像同步代码一样书写。它有三种状态:pending(进行中)、fulfilled(已完成)、rejected(已拒绝)。
② async/await 是基于 Promise 的语法糖,使得异步代码的写法更简洁、易读。async 用来声明一个函数是异步的,await 用来等待 Promise 完成。使用 async/await 使得异步代码看起来像同步代码,减少了回调地狱和链式调用的复杂性。await 只能在 async 函数内使用。
③ setTimeout 是一个 JavaScript 定时器,用于在指定的延迟时间后执行某个函数。它并不是处理异步操作的专用工具,而是用于延迟执行某个代码块。它不会阻塞后续代码的执行,但会在指定的时间后触发回调函数。setTimeout 会返回一个定时器ID,方便后续调用 clearTimeout 来取消定时任务。
23.什么叫原型链?
原型链:通过隐式原型把一些构造函数层层的串起来
① 每个函数都有一个原型属性(prototype) , 这个属性是一个指针,指向构造函数的原型对象( CreateObj.prototype)
② 在默认情况下,所有原型对象都会自动获得一个constructor属性,该属性包含一个指向prototype属性所在的函数
③ 所有的实例( 通过构造函数new出来的,都包含一个隐式原型(__proto__),该指针指向实例的构造函数的原型对象
④ 写在构造函数中, 为this赋值的属性和方法
⑤ 写在原型对象上的方法或者属性
⑥ 当一个对象访问属性和方法的时候,他的访问规则叫(就近原则)
24.TypeScript了解吗?
TypeScript 是一种由微软开发的开源编程语言,它是 JavaScript 的超集,主要增加了静态类型和类型检查功能。通过 TypeScript,你可以在编写代码时提前发现类型错误,进而提升代码的质量和可维护性。 Typescript并不直接在浏览器上运行,需要编译器编译成纯Javascript来运行。
1)静态类型
TypeScript 提供了强类型的支持,可以为变量、函数参数、返回值等指定类型。这在大型项目中尤为有用,可以在编译时发现潜在的错误。
let num: number = 10; // num 必须是一个数字
let message: string = "Hello, TypeScript!"; // message 必须是一个字符串
2)接口(Interface):
TypeScript 提供了接口(interface)来定义对象的结构,可以帮助确保对象符合特定的格式。
interface Person {
name: string;
age: number;
}
const person: Person = {
name: "Alice",
age: 25
};
3)类(Class)与继承(Inheritance):
TypeScript 支持类和继承,且可以指定类的属性和方法类型,帮助确保代码的结构更清晰。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move() {
console.log(`${this.name} is moving.`);
}
}
class Dog extends Animal {
bark() {
console.log(`${this.name} is barking.`);
}
}
const dog = new Dog("Buddy");
dog.bark();
dog.move();
4)泛型(Generics):
TypeScript 支持泛型,让你可以编写更灵活和可重用的代码。泛型允许在类、函数和接口中使用类型变量,以便在不同的数据类型间重用代码。
function identity<T>(arg: T): T {
return arg;
}
console.log(identity(1)); // 返回 1
console.log(identity("hello")); // 返回 "hello"
5)类型推断:
TypeScript 可以根据你的代码推断出变量的类型,而不必显式声明类型。
let num = 10; // TypeScript 推断 num 的类型为 number
6)ES6 和 ES7 特性支持:
TypeScript 支持最新的 JavaScript 特性,如箭头函数、模板字符串、async/await 等。
25.双向数据绑定在vue3.0和vue2.0之间的区别
1)响应式系统实现方式
Vue2.0使用Object.defineProperty对对象属性进行劫持,通过定义getter和setter实现数据监听,但无法直接监听新增属性或数组变化,需通过Vue.set等特殊方法处理
Vue3.0采用ES6的Proxy代理对象,可拦截包括属性增删、数组操作在内的多种操作,无需额外API即可实现全面的响应式支持
2)性能优化
Vue2.0在初始化时会对所有数据创建观察者(Watcher),数据量大时可能影响页面加载性能
Vue3.0通过懒观察(Lazy Observation)仅对渲染用到的数据创建依赖,并利用Proxy的精确变更通知,仅更新相关视图,减少不必要的渲染开销
3)数据类型支持与灵活性
Vue2.0需递归遍历对象属性实现响应式,且对嵌套对象或数组的处理较复杂
Vue3.0的Proxy直接监听整个对象,支持动态新增属性、删除属性及数组索引操作,简化了复杂数据结构的处理
4)TypeScript支持
Vue3.0的响应式系统基于Proxy设计,天然适配TypeScript类型推断,提供更完善的类型支持,而Vue2.0的类型系统相对较弱
5)API设计差异
Vue2.0通过data选项和v-model指令实现双向绑定,依赖选项式API
Vue3.0引入reactive()和ref()等Composition API,允许更灵活的组合逻辑,同时保留v-model的语法糖特性
26.watch和watchEffect的区别?
// 监听原始类型数据
watch(count, (newVal, oldVal) => {})
watch([one, two], ([newOne, newTwo], [oldOne, oldTwo]) => {})
// 监听对象的某个属性,使用getter函数
watch(()=>obj.id, (newVal, oldVal) => {})
// 深度监听对象内部变化
watch(obj, (newVal, oldVal)=>{}, {deep: true, immediate: true})
// watchEffect会自动收集函数内响应式数据作为依赖、初始化时立即执行一次、当函数内依赖的响应式数据变化时重新执行
watchEffect(() => {})
// watchEffect返回一个停止函数,调用它可以停止监听
const stop = watchEffect(()=>{});
stop()
// watchEffect的回调函数可以返回一个清理函数
watchEffect((onInvalidate)=> {
// 清理函数,在下次执行前或停止监听时调用
onInvalidate(() => {})
})
26.css中样式的优先级:
!important>内联>ID选择器>类、属性、伪类选择器>元素、伪元素选择器>通配(*)
27.Render函数
render函数是 Vue 渲染组件时的入口,类似于模板的作用,但是它是通过 JavaScript 代码来描述组件如何渲染。
语法:
render(h) {
// h是createElement函数,或者说是h函数
return h('div', { class: 'container' }, [
h('h1', 'Hello Vue 3!')
]);
}
render函数接收一个参数 h,这个 h 就是 Vue 的 createElement 函数,它用于创建虚拟 DOM。
render函数通常返回一个由 h 函数组成的虚拟 DOM 树,表示该组件如何渲染。
用法:
适用于复杂的组件逻辑,或动态创建组件的场景。
在Vue 2.x中可以使用 render 函数来替代模板语法,进行更灵活的渲染控制。
在Vue 3中,render 函数通常在 Vue 组件中用于返回一个由 h 函数创建的虚拟 DOM。
28.h函数(createElement):
h函数是 Vue 3 中的一个内置函数,用于创建虚拟 DOM 元素(VNode)。它被用于描述一个 DOM 节点(或组件)及其属性、子节点、事件等。
语法:
h(tag, props, children)
tag: DOM元素的标签名称(如 div, span, h1 等),或者 Vue 组件的名称。
props:用于设置元素或组件的属性、事件等。
children:可以是其他子节点(可以是字符串、数组或者其他 VNode)。
示例:
h('div', { class: 'container' }, [
h('h1', 'Hello, World!'),
h('p', 'This is a paragraph.')
]);
这段代码会渲染为:
<div class="container">
<h1>Hello, World!</h1>
<p>This is a paragraph.</p>
</div>
h函数的返回值:
返回一个虚拟DOM对象(VNode),这个对象会被 Vue 渲染引擎转化为真实的 DOM 元素。
29.render函数和 h 函数的关系
在Vue中,render 函数负责定义组件的渲染方式,而 h 函数是构造虚拟 DOM 的工具。
在render函数中,h 函数用来描述 UI 的结构,通过它可以在不使用模板语法的情况下定义组件的渲染逻辑。
使用场景:
Vue 3中,render 函数和 h 函数结合使用,用于替代 Vue 2.x 中的模板语法。它们使得组件的渲染更具灵活性,特别是当你需要在组件中进行动态渲染或自定义渲染时。
render和 h 特别适合在以下场景中使用:
条件渲染:可以使用h函数创建不同的 VNode 来决定渲染哪些内容。
循环渲染:可以用h函数结合 map 等方法动态生成多个子节点。
动态组件:h函数可以动态创建组件并传递不同的属性或事件。
示例:动态渲染列表项
export default {
render() {
return h('div', [
this.items.map(item => {
return h('p', item);
})
]);
},
data() {
return {
items: ['Vue', 'React', 'Angular']
};
}
};