最近正在找工作,整理一些面试题,给自己加油!!!
JS实现两个数组的交集
- Set和filter()
function intersect(arr1,arr2){
const set = new Set(arr1)
return arr2.filter(item => set.has(item))
}
- Set和Array.form()
function intersect(arr1,arr2){
const set1 = new Set(arr1)
const set2 = new Set(arr2)
const intersection = new Set([...set1].filter(x => set2.has(x)))
return Array.from(intersection)
}
- map和reduce()
function intersect(arr1,arr2){
const map = new Map()
arr1.forEach(item => map.set(item, (map.get(item) || 0) + 1))
return arr2.filter(item => map.has(item) && (--map.get(item) >= 0))
}
git合并某条提交记录到当前分支
- git cherry-pick 完整哈希值
Content-Type的值有哪些?
- JSON数据:application/json
- 表单数据:
- application/x-www-form-urlencoded:用于发送键值对,键和值之间用等号分隔,每对之间用&符号分割;常用于简单的表单数据
- multipart/form-data:表单包含文件上传时
- application/json:用于发送JSON编码的表单数据
- application/x-www-form-urlencoded;charset=UTF-8;指明了使用的字符集是UTF-8
CommonJS和ESModule的区别
- 语法差异:CommonJS使用require导入模块,使用module.exports或exports来导出模块;ESModule使用import\export来导入导出模块;
- 加载机制:CommonJS是同步加载模块,这意味着在执行require时,程序会暂停直到模块加载完成;ESModule是异步加载,可以在编译时确定模块依赖,支持静态分析,从而预测性的进行代码分割和按需加载;
- 缓存和重新执行:CommonJS在第一次加载模块时执行模块代码并缓存结果,之后每次调用都会返回相同的缓存结果;ESModule导出的是值的引用,不缓存模块执行的结果,而是缓存模块的解析结果;
- 顶层this指向:CommonJS中,顶层this指向模块对象本身;ESModule中,顶层this通常执行undefined;
- 执行上下文:ESModule中每个模块都有自己的独立作用域,且默认处于严格模式;CommonJS模块虽然也有自己的作用域,但在ES6之前并不强制使用严格模式;
- 动态导入:ESModule支持动态导入(import()表达式),允许在运行时有条件的加载模块;CommonJS 不支持动态导入,所有的require必须在模块的顶层声明;
- 兼容性:CommonJS最初设计用于服务器JsvaScript(如Node.js),在浏览器环境中不被原生支持;ESModule在现代浏览器是原生支持的,但在旧版浏览器中需要转译
Map和对象的区别
- 键类型:Map的键可以是任意数据类型,包括对象、函数、数组、基本类型等;对象Object的键只能是字符串或Symbol类型
- 顺序保证:Map会保持键值对的插入顺序;普通Object不保证键值对的顺序;
- 大小获取:Map有个size属性,可以直接获取当前Map中键值对的数量。Obejct没有这样的属性;
- 迭代:Map的迭代方法:forEach、for…of;Object可以通过Object.keys()、Object.values()和Object.entries()将其转换为数组进行迭代,for…in循环会枚举原型链上的属性;
- 原型链:Map没有原型链,因此不会继承额外的属性或方法;Object有原型链,意味着他们可以继承自其他对象,可能会影响键的查找和迭代;
- 性能:在有些情况下,Map的性能可能优于Object,尤其在键的类型多样且需要频繁插入删除的情况下;Object在处理字符串键时可能有更快的查找速度;
- 互操作性:Map在ES6引入,可能在较旧的浏览器中不被支持,而Object则几乎在所有浏览器中都有很好的支持
跨域的方式
- 跨域通常发生在当Web应用尝试从不同的源(即不同的域名、协议或端口)请求资源时,浏览器的同源策略限制了这种行为。
- JSONP
- 原理
- 利用 < script >标签没有跨域限制的特性;
- 客户端定义一个全局函数,通过< scipt >标签的src属性请求数据,数据被封装成一个函数调用的形式返回
- 服务器响应的数据格式类似callbackName({‘key’: ‘value’})
- 使用场景
- 仅支持GET请求
- 原理
- CROS
- 原理
- 服务器通过HTTP响应头Access-Control-Allow-Origin指定哪些源可以访问其资源
- 可以允许特定的源或者所有源(*)
- 使用场景
- 现代浏览器和API支持CROS
- 支持所有HTTP方法
- 原理
- window.postMessage
- 原理
- 允许不同源的窗口对象之间进行通信
- 发送方通过postMessage方法发送消息,接收方通过message事件监听消息
- 使用场景
- iframe与父窗口或其他iframe之间的通信
- 原理
- NGINX反向代理
- 服务器端代理,通常用于生产环境
- Websocket
- 原理:
- Websocket协议本身支持跨域,建立连接后可以在两个端点之间进行全双工通信
- 原理:
- document.domain + iframe
- 当两个窗口的主域名相同,但子域名不同,通过设置document.domain为相同的顶级域名来绕过同源策略
- 使用与子域名之间的跨域通信
MVVM SPA
- MVVM:主要是将原有的主动调度 变成可以向上可以向下的绑定层
- model:数据结构
- view:视图
- viewModel:数据层与视图层的绑定层
- MVC
- model:数据结构
- view:视图
- controller:数据结构与视图展示的调度
- SPA
- single page application 单页面应用
- 整个应用只有一个模版index.html
- 优点:用户体验好,对服务压力小,前后端分离
- 缺点:初次加载耗时,SEO难度较大
计算属性computed计算的结果可以修改吗
- 可以修改的;需要写成get()、set()形式
methods和computed的区别
- computed是有缓存机制的,methods没有(调用几次就执行几次)
数据更新了,视图没有更新
- this.$set
Vue2中的Diff算法
- Vue2中的diff算法主要用于更新虚拟DOM到实际DOM。当组件的状态发生变化时,Vue需要重新渲染组件的虚拟DOM树,并将其与之前的虚拟DOM树进行比较,找出需要更新的部分,然后仅更新实际DOM中必要的部分,而不是重绘,可以提高性能;
- diff算法只在同一层级的虚拟节点进行比较
- 双端比较:从数组的两端开始,逐步向中间移动
- key的使用:当使用key属性时,Vue可以更有效的识别和追踪节点,当key值不同的节点出现在同一个位置时,Vue会认为他们是不同的节点,并创建新的节点同时销毁旧的节点。如果key相同,即便节点的位置改变了,Vue也会尝试复用节点,仅更新其属性和子节点;
- patch函数用于比较和更新节点,updateChildren函数用于比较子节点数组
Vue二次封装el-select滚动加载数据,讲一下大概思路
- 创建自定义组件:创建一个新的vue组件,包含el-select组件,并对其进行封装;
- 滚动事件发生在下拉菜单上面,所以需要监听.el-slect-dropdown__warp元素的滚动事件;
- 判断是否滚动到底部:scrollHeight(内容可视区域的高度加上滚动的距离) - scrollTop(滚动的距离) <= clientHeight(内容可视区域的高度)
- 加载更多数据
- 更新状态和数据
- 防止重复加载
Vue首屏优化如何处理
- 路由懒加载:import()
- 代码分割
- 异步组件使用
- 延迟加载非关键组件:keep-alive
- 压缩与优化资源
- 压缩图片与其他静态资源
- 使用CDN
- 优化HTTP请求
延迟加载JS有哪些方式
- async:async和html同步执行的,谁先加载完js谁先执行;
- defer:等html全部解析完成后,才会执行js代码,顺次执行js脚本;
- defer和async加在scirpt标签上,在html解析到scirpt标签时,都会立即加载,加载不会阻塞html的解析。
- setTimeout
自定义组件的v-model
- 在Vue中,v-model提供一种在表单输入元素(input、select、textarea)和组件之间进行双向数据绑定的简便方式;
自定义组件的v-model在vue2和vue3有什么区别
- 相同点:用在表单都是给input绑定一个value值和input事件;
- v-model只能使用一次,但是在vue3中,在v-model后添加参数可使用多次
- Vue2默认传递value属性,接受input事件;
- Vue3默认传递modelValue属性,接受update:modelValue事件,当在v-model后添加参数类似v-model:myPropName,则传递myPropName属性,接受update:myPropName事件;
- Vue2默认传递的属性和事件可通过model选项进行修改;
- Vue3默认传递的属性和事件无法修改,必须事modelValue和update:modelValue
.sync修饰符的作用
- .sync修饰符主要用于简化父组件与子组件之间的双向数据绑定;
Vuex页面刷新state是否存在?怎么做持久化存储
- Vuex本身不是持久化存储;页面刷新后state不存在了
- 可以用localstrage、sessionstrage或者插件
Vuex有哪些属性?
- state:全局共享属性
- getters:针对于state的二次计算
- mutations:存放同步方法
- actions:存放异步方法,并且提交mutations
- modules:把vuex再次进行模块化划分
Vuex使用state的值
- this.$store.state.xxxx:可以直接修改vuex中的state的值
- mapState:不能修改
组件使用了getters中的内容,组件采用v-model的形式会发生什么
- 不修改就没问题 如果值变了就会报错;getters不能直接修改数据
Vuex的mutations和actions的区别
- 两者都是用来存放全局方法的;全局方法return值拿不到
- mutations是同步操作;actions是Promise对象,可以执行相关异步操作
- mutations是修改state的值,actions是提交mutations
路由的模式和区别
- 路由模式:history 和 hash
- hash模式的原理:Vue Router监听浏览器的 onhashchange 事件,当哈希值发生改变时,Vue Router会捕获这个变化并相应的更新视图
- history的原理:使用HTML5的pushState和replaceState方法来改变浏览器的URL,同时监听popstate事件来响应浏览器前进和后退按钮的操作;
- 当找不到页面时,history会向后端发送一次请求;hash不会;
- hash模式地址栏会有#号,history没有
- 项目打包后:history模式后台需要做相关配置,否则页面会在再次刷新的时候报404,hash模式
- 相同点:当URL改变时,页面不会重新加载,都受页面导航回退前进影响
$refs在通信时的弊端
- $refs是一种用于访问组件实例或DOM元素的方法;
- 违反组件封装性:Vue鼓励每个组件管理自己的状态,而通过$refs直接访问和修改子组件的状态可能导致代码难以维护和测试
- 异步更新问题:Vue的响应式系统是异步更新DOM的,可能导致使用$refs访问一个元素或组件时得到的还是未更新的值;需要确保在DOM更新后使用,在mounted执行或者使用nextTick方法;
- 性能影响:过度使用$refs可能会导致不必要的DOM操作,特别是当这些操作频繁发生时。直接操作DOM可能比使用Vue的响应式API效率低,因为后者会尽可能的优化更新;
- 与Vue的单向数据流原则相悖
如何获取事件对象
- 事件对象是JavaScript中用于存储和传递事件相关信息的对象;
- window.event
- 使用event参数
- 使用$event属性
什么是three.js
- three.js是一个用于创建3D图形的JavaScript库。它是一个开源项目,由WebGL和HTML5 canvas驱动
three.js的主要特点是什么
- three.js的主要特点是易于使用、灵活性和高性能;
- three.js提供了许多实用的功能和工具,如场景管理、光照、材质和动画等,同时也支持自定义着色器和自定义缓冲区;
ThreeJS 中的几何体是什么?
- 几何体是ThreeJS用于创建3D模型的基本构建块。这些几何体包括立方体、球体、圆柱体、圆环体、平面等;
ThreeJS 中的组是什么?
- 组是ThreeJs中用于组合多个对象的容器;可以将对象添加到组中,以便一起移动、旋转或缩放他们;
ThreeJS 中的相机是什么?
- 三维空间需要一个相机来拍摄场景;有多种相机类型:透视相机(PerspectiveCamera)、正交相机(OrthographicCamera)等;
ThreeJS 中的渲染器是什么?
- 渲染器是ThreeJs中用于将创建的场景呈现在屏幕上的核心组件。它使用WebGL或canvas技术将场景中的图形绘制到浏览器中;
ThreeJS 中的光源有哪些类型?
- 环境光(AmbientLight)、点源光(PointLight)、平行光(DirectionalLight)和聚光灯(SpotLight)
ThreeJS 中的材质有哪些类型?
- 基础材质(MeshBasicMaterial)、标准材质(MeshStandardMaterial)和物理材质(MeshPhysicalMaterial)等;
three.js如何创建一个简单的3D场景
- 创建Three.js场景需要创建一个场景对象,并将所需的几何体、光源、相机等添加到场景中;
forEach和Map的区别
- 相同点
- 都是循环遍历数组中的每一项;
- 每次执行匿名函数都支持三个参数(item,index,array);
- 匿名函数中的this都是指向window;
- 只能遍历数组;
- 不同点
- forEach()方法返回undefined;map()方法返回一个包含转换后元素的新数组;
- forEach()允许callback更改原始数组的元素,map()返回新的数组
- map()是可链接的,forEach()是不可以的,它是返回undefined;
SVG和Canvas的区别
- SVG和Canvas是两种用于在Web上绘制图形的不同技术;
- Canvas使用JavaScript和HTML元素来绘制图形;SVG使用XML语法来绘制图形;
- Canvas通过像素来渲染图形,适合绘制简单的图形和文字;SVG通过DOM节点渲染图形,适合绘制复杂的矢量图形;
- 如果SVG节点过多,会导致渲染速度过慢,而Canvas的性能更好一点;
- Canvas依赖分辨率,放缩时存在失真的问题;而SVG不依赖分辨率,放缩时不会失真;
- Canvas不支持事件,只能通过库实现;而SVG支持分层和事件;
Vue判断token失效后,怎么取消未完成的请求
- 使用Axios进行HTTP请求时,通过请求拦截器来判断token是否失效,并在确定token失效后取消未完成的请求;
- 定义一个取消请求的源:使用Axios提供的CancelToken和cancelTokenSource创建一个用来取消请求的源
- 在请求拦截器中使用这个取消源:当发送请求时,将这个取消源传递给请求配置对象
- 当检测到token失效时,调用取消源的cancel方法来取消所有相关的未完成请求
用Promise实现红绿灯不断交替亮灯的逻辑
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
var light = (timmer, cb){
return new Promise((resolve,reject) => {
setTimeout(function(){
cb()
resolve()
}, timmer)
})
}
var step = fucntion(){
Promise.resolve().then(function(){
return light(3000, red)
}).then(function() {
return light(2000, green)
}).then(function(){
return light(1000, yellow)
}).then(function(){
step()
})
}
step()
JS 实现 Promise.all方法
let a = new Promise((resolve) => resolve(1))
let b = new Promise((resolve) => resolve(2))
let c = new Promise((resolve) => resolve(3))
let PromiseAll = (promiseall) => {
return new Promise((resolve,reject) => {
if(!Array.isArray(promiseall)){
reject(new TypeError('不是数组'))
}
let results = []
let nums = 0
promiseall.forEach((item,index) => {
Promise.resolve(item).then(res => {
results[index] = res
nums++
if(nums == promiseall.length){
resolve(results)
}
}).catch(err => {
reject(new Error(err))
})
})
})
}
PromiseAll([a,b,c]).then(res => {
console.log(res)
})
实现mergePromise函数,把传进去的数组按顺序先后执行,并且把返回的数据先后放到数组data中。
const time = (timer) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timer);
});
};
const ajax1 = () =>
time(2000).then(() => {
console.log(1);
return 1;
});
const ajax2 = () =>
time(1000).then(() => {
console.log(2);
return 2;
});
const ajax3 = () =>
time(1000).then(() => {
console.log(3);
return 3;
});
let mergePromise = (promiArr) => {
// 在这里写代码
let data = []
let promise = Promise.resolve()
console.log(promise)
promiArr.forEach(item => {
promise = promise.then(item).then(res => {
data.push(res)
return data
})
});
return promise
}
mergePromise([ajax1,ajax2, ajax3]).then(data => {
console.log(data)
})
// 1 2 3 [1,2,3]
vue是怎么挂载实例的
- Vue挂载过程就是将模板编译成虚拟DOM,再将虚拟DOM渲染成真实DOM,并进行数据的响应式处理。
Object.defineProperty如何监听数组?为什么无法获取数组的变化?
- Object.defineProperty是JavaScript用来定义或修改一个对象的属性特性的函数;
- Object.defineProperty主要用在对象的某个属性上设置getter和setter方法,从而可以访问或修改该属性时执行一些代码;
- 数组的原生方法(如push、pop、splice、unshift等)会直接修改数组的内部结构和长度,而这些方法的调用不会触发属性的setter
- 重写数组方法:重写数组原型上的方法:push、pop等,使得当这些方法被调用时,Vue能够更依赖于数组的数据绑定
- 使用 s e t 或 set或 set或delete方法:Vue提供了 s e t 或 set或 set或delete方法来确保在数组中添加或删除项时能够正确触发视图的更新;
- 深拷贝数据
你了解Node.js吗
- Node.js是一个基于Chrome v8引擎的服务器端JavaScript运行环境;
- Node.js是一个事件驱动、非阻塞式的I/O模型,轻量而又高效;
- Node.js的包管理器npm式全球最大的开源库生态系统
Node.js的使用场景
- 高并发、实时聊天、实时消息推送、客户端逻辑强大的SPA(单页面应用程序)
Node.js的特点
- 功能强大、非阻塞式I/O\,在较慢的网络环境中,可以分块传输数据,事件驱动,擅长并发访问
- 轻量级:Node.js本身即是代码又是服务器
- 可扩展:可以轻松应对多实例、多服务器架构,同时拥有海量的第三方库的组件
Node.js的全局对象
- global
- process
- console
- exports
- module
JS实现阻塞
- setTimeout
- Promise
- async/await
- Generator
JS判断一个变量是否是数组的方法
- Array.isArray()
- instanceof(arr instanceof Object // true)
- constructor
- object.prototype.toString.call()
- Array.protoType.isProtoType()
数组与链表的区别
- 存储方式不同:数组是连续存储,链表是链式存储,链表在内存空间不一定是连续的;
- 访问元素方式不同:数组可以通过下标随机访问,单向链表只能通过头结点从前向后访问链表中的元素;
- 增删效率不同:数组在进行增删时需要移动其他链表中的元素,时间复杂的为O(n)。链表进行插入删除时,找到要插入或删除的位置后,增删时间复杂度为O(1)。
前端清除缓存的方法
- 使用快捷键
- 修改请求链接:在请求链接中添加随机数和或时间戳
- 设置响应头:Cache-Control为no-cache或must-revalidate,告知浏览器不适用缓存
- 使用meta标签:
- 配置webpack打包输出文件名
- 给资源文件加时间戳
浏览器缓存原理
- 浏览器缓存分为强缓存和协商缓存
- 强缓存:只要没到有效期,就继续使用本地离线资源,不向服务器发送请求
- 协商缓存:本质使用本地的缓存资源和服务器的缓存资源相对比,看看是否一致或是否已更新,如果未更新,就继续使用本地离线资源,否则重新发送请求
HTTP和HTTPS的不用之处
- 安全性:HTTP是一种明文传输协议,数据在传输过程中不加密;HTTPS通过使用TLS或SSL加密协议对HTTP增强,数据加密
- 建立连接过程与响应速度:HTTP连接建立响应速度相对较快,客户端发送请求,服务器返回响应,完成请求响应后即断开连接;HTTPS首先需要进行SSL/TLS握手,确保双方之间建立安全的通信通道,握手完成后才能进行HTTPS通信
- 默认端口:如果网址以http://开头,默认会使用HTTP协议连接到端口80;如果网址以https://开头,则会使用HTTPS协议连接到端口443
- 证书要求。HTTP不需要使用数字证书。HTTPS要求使用SSL/TLS数字证书,这些数字证书由受信任的第三方机构(称为证书颁发机构或CA)签发。证书用于验证服务器身份,并确保数据传输的完整性和加密性质;
防抖和节流的原理及应用场景
- 防抖:规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效;
- 防抖原理:是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置,这样一来只有最后一次操作才能被触发
- 防抖应用:1、实时搜索信息;2、文本的输入验证;3、按钮提交事件;4、判断scroll是否滚动到底部;
- 节流:在事件被触发n秒后再执行回调,如果在n秒内又被触发,则重新计时,重新触发定时器
- 节流原理:在第一次触发了setTimeout后,先把阀门关闭,等执行完后再把阀门打开;
- 节流应用:1、窗口调整;2、页面滚动请求;3、DOM元素的拖拽功能实现
node 和 浏览器的事件循环有什么区别
- 执行环境:浏览器的事件循环运行在浏览器中,node的事件循环运行在node.js中,浏览器的事件循环负责处理浏览器的事件、用户交互、渲染等;而node的事件循环主要处理I/O操作和网络请求等;
- 两个都将任务分为宏认为和微任务,但是浏览器的微任务包括Promise、MutationObserver和queueMicrotask、node的微任务包括Promise 、nextTick
- 运行机制不同:浏览器的事件循环是单线程的,通过异步回调函数和事件触发来实现非阻塞的异步操作,node的事件循环是基于Libuv,利用来底层操作系统提供的多线程特性,使node能够处理更高的并发请求。
事件循环为什么要区分宏任务和微任务?
- 主要是为了解决JavaScript引擎中不同任务之间的执行优先级问题
- 更好的协调任务的执行优先级,提高JavaScript的运行效率和代码的可读性
Vue开发过程中使用的自动化测试
- 单元测试:工具:Jest Mocha+chai;单元测试关注代码的最小测试单元。如函数、方法
- 组件测试:工具:Vue Test Utils结合Jest或Mocha;使用mount()或shallowMount()函数渲染组件,通过模拟用户交互验证组件的行为和输出
- 端到端(E2E)测试:工具:cypress和Nightwatch.js;从浏览器角度验证整个应用功能,可以测试页面导航、表单提交、异步操作响应等;
一个页面从输入URL到展示的过程
- DNS解析:浏览器中输入一个URL地址,浏览器首先会进行DNS解析,将域名转换为IP地址。由本地DNS服务器完成
- 建立TCP连接:浏览器得到IP地址后,会尝试建立一个与服务器的TCP连接。在建立连接之前,浏览器需要通过三次握手协议与服务器进行通信确认。
- 发送HTTP请求:请求访问指定的资源。HTTP是应用层协议,主要用于客户端和服务器之间的通信。
- 服务器处理请求并返回HTTP响应
- 浏览器解析渲染页面:
浏览器是怎么解析文档的?用什么解析
- 浏览器内核是浏览器的核心组件,负责解析HTML、CSS;执行JavaScript;
- 浏览器内核包括渲染引擎和JavaScript引擎
- 渲染引擎先解析HTML,构建出DOM(文档对象模型)树,根据CSS样式信息,计算出每个元素在页面上的位置和尺寸,最终将所有元素渲染到屏幕上;
- JavaScript引擎负责解析和执行JavaScript代码,为网页提供动态交互和数据处理能力;
302怎么确认重定向路径
- 301是永久重定向 302是临时重定向
- 服务器返回http状态码302,其中包含Location头字段,其中包含新的URL,客户端会发送一个新的请求到新的URL,以获取所需的资源。
移动端怎么适配
- 媒体查询
- viewport+rem适配
- flex布局
- vw/vh
性能优化的方案
- 减少页面的重绘和回流:减少使用css的快捷方式
- 函数的防抖、节流
- 减少HTTP的请求次数
- 资源和数据使用缓存
- 运行条件少时使用v-if;需要频繁切换时使用v-show
- computed 和 watch 分场景使用
- 图片懒加载、路由懒加载
- ui组件库按需引用
- 事件及时销毁
- 组件使用keep-alive缓存
- 使用webpack对图片进行压缩
- 提取公共代码
- 提取组件的css
- 开启gzip压缩
webpack做了哪些优化
- 拆分代码
- 懒加载
- Tree Shaking :减少打包后文件大小
- 代码压缩
- 配置缓存
- 第三方库的优化
- 并行构建
- 优化文件体积
- 使用缓存
- 优化图片资源
- 配置合理的模块解析规则
tree shaking原理
- Tree shaking就是移除JavaScript上下文中未引用的代码;
- 在去除代码冗余过程中,程序会从入口文件出发扫描所有的模块依赖,以及模块的子依赖,然后将他们链接起来形成一个抽象语法树(AST)。随后运行所有代码,查看哪些代码是用到过的,做好标记,最后再将抽象语法树中没有用到的代码摇落,这样就去除了没有用过的代码。实现的关键在于ES Module模块的静态分析
http请求数据的方式
- GET:请求指定的页面信息,并返回实体内容
- POST:表示向指定资源提交数据,数据包含在请求头中,POST请求有可能会导致新的资源建立或已有资源的修改
- HEAD:类似于GET,只不过返回的响应体中没有具体报文,只有报文头,用于获取报文头;
- PUT:从客户端向服务器传送的数据取代指定的内容,即向指定的位置上传最新的内容;
- PATCH:对PUT方法的补充,用来对已知资源进行局部更新;
- OPTIONS:返回服务器针对特殊资源所支持的HTML请求方式或允许客户端查看服务器的性能;
- DELETE:请求服务器删除Request-URL所标识的资源;
- CONNETCT:HTTP1.1中预留给能够将连接改为管道方式的代理服务器;
- TRACE:回显服务器收到的请求,主要用于测试和诊断;
HTTP和Websocket有什么区别
- 连接方式:HTTP是一种无状态的协议,每次请求都需要建立一个新的连接,完成请求后立即关闭连接;Websocket是一种全双工的协议,他在客户端和服务器之间建立一条持久的连接,可以实现双向通信;
- 数据传输:HTTP协议是基于请求-响应模式的,客户端发送请求,服务器返回响应;Websocket是允许服务器主动向客户端推送数据,实现了服务器和客户端之间的双向通信;
- 数据格式:HTTP协议传输的数据通常是文本或二进制数据,Websocket可以传输任意格式的数据,包括文本、二进制、JSON等;
- 端口:HTTP协议使用的默认端口是80(HTTP)或443(HTTPS),而Websocketde的默认端口是80(WS)或443(WSS)
Websocket是怎么建立连接的
- 客户端发送一个HTTP请求到服务器,请求中包含希望升级为Websocket协议的信息,即在请求头中包含Upgrade字段,值为webscoekt:Upgrade: websocket和Connection: Upgrade
- 服务器收到请求后,会返回一个HTTP101状态码,表示同意升级为WebSocket协议,同时在响应头中添加Upgrade和Connection字段,告知客户端已升级为WebSocket协议;
- 客户端收到服务器的响应后,通过TCP 通道进行传输通信
Websocket协议的主要特点
- 单一的TCP连接:使用单一的TCP连接进行全双工通信,避免了传统的HTTP协议需要建立多个连接的缺陷;
- 双向平等对话:允许客户端和服务器任意时刻发送信息,不再需要轮询或主动连接;
- 头部信息、Cookie和身份验证:Websocket协议没有头部信息、Cookie和身份验证等开销,因此性能开销小,通信效率高;
- 保持链路激活:通过“ping/pong”帧来保持链路激活,避免因长时间无数据交互而断开的连接;
- 全双工模式:客户端和服务器可以随时发送信息;
- 与HTTP协议的良好兼容性;
- 可以发送文本或二级制数据
- 无同源限制
setTimeout与nextTick的区别
- nextTick会在Vue的下一个DOM更新循环结束时执行操作,确保在数据变化后DOM已经更新
- setTimeout则是在指定的延迟时间后执行代码,不关心DOM 的更新状态
- nextTick的优先级高于setTimeout
- nextTick是一个异步操作
nextTick的原理
- 利用事件循环机制,在DOM更新之后执行回调函数。他可以确保回调函数在合适的时机执行,并且可以进行一下优化处理,以提高性能
宏任务与微任务有哪些
- 宏任务:整体代码script、setTimeout、setInterval、setImmediate、I/O操作(输入输出,读取文件操作、网络请求)、ui render(dom渲染,即更改代码重新渲染dom的过程)、异步ajax;setImmediate>setTimeout>setInterval>I/O操作>异步ajax
- 微任务:Promise(then、catch、finally)、async/await、process.nextTick、Object.observe(用来实时监测js中对象变化)、MutationObserve(监听DOM树的变化); process.nextTick > Promise
- 同步任务>微任务>宏任务
flex三个属性:flex-grow flex-shrink flex-basis
- flex-basis:当flex布局的默认主轴方向为row时,默认控制元素的宽度;当主轴方向为cloum时,默认控制元素的高度;
- flex-grow:定义子元素的放大比例:
1.该属性用来设置当父元素的宽度大于所有子元素的宽度和时(即父元素会有剩余空间),子元素会如何分配父元素的剩余空间;
2.默认为0;即使存在剩余空间,也不会放大
3.所有项目flex-grow为1时,等分剩余空间 - flex-shrink:定义子元素的缩小比例:
1.该属性用来设置当父元素的宽度小于所有子元素的宽度和时(即子元素会超出父元素),子元素会如何缩小自己的宽度
2.默认为1;即如果空间不足,该项目将会缩小
3.所有项目flex-shrink为1时,当空间不足时,缩小的比列相同;
5.lex-shrink 为 0:空间不足时,该项目不会缩小
flex:1 是什么意思?
- flex:1是一个简写方式;相当于设置:flex-grow:1;flex-shrink:1;flex:basis:0
- 意思是让子项目将会占用容器中所有可用的剩余空间,以实现均匀分布;
- 使用场景:适合等分布局(可用于某高度或宽度固定 ,其中宽度或高度自适应并滚动)
flex:auto 是什么意思?
- flex:auto 相当于 flex: 1 1 auto;flex-grow: 1 flex-shrink:1 flex-basis: auto
- 子项目可放大也可缩小;具有十足的弹性,但在尺寸不足时会优先最大化内容尺寸;
- 使用场景:适合基于内容动态适配的布局
flex:0 是什么意思?
- flex:0是一个简写方式;flex: 0 1 0; 相当于设置:flex-grow:0;flex-shrink:1;flex:basis:0
- 子项目不会放大但会缩小;最终尺寸表现为最小内容宽度
- 适用场景较少,适合设置在替换元素的父元素上;
flex:none 是什么意思?
- flex:none: 相当于 flex: 0 0 auto; flex-grow:0 flex-shrink:0 flex-basis:auto
- 子项目不会放大也不会缩小;最终尺寸表现为内容的宽度
- 使用场景:flex子项的宽度就是其内容的宽度,且永远不会换行
css实现高度或宽度自适应
css实现左侧宽度固定右侧宽度自适应
- 定位
<body>
<div class="left">
定宽
</div>
<div class="right">
自适应
</div>
</body>
<style>
.left{
width: 200px;
height: 100px;
position:absolute;
top: 0;
left: 0
}
.right{
height: 100px;
}
</style>
- 浮动
<body>
<div class="left">
定宽
</div>
<div class="right">
自适应
</div>
</body>
<style>
.left{
width: 200px;
height: 100px;
float:left
}
.right{
height: 100px;
}
</style>
- margin
<body>
<div class="left">
定宽
</div>
<div class="right">
自适应
</div>
</body>
<style>
.left{
width: 200px;
height: 100px;
}
.right{
height: 100px;
margin-top:-100px;
margin-left: 110px
}
</style>
弹性盒模型实现自适应
- 上下高度固定中间高度自适应
<div id="contain">
<div id="top">你好</div>
<div id="center">你好</div>
<div id="bottom">你也好</div>
</div>
#contain{
display: flex;
flex-direction: column;
}
#top,#bottom{
height: 200px;
}
#center{
flex:1
}
- 左侧宽度固定右侧宽度自适应
<div id="contain">
<div id="left"></div>
<div id="right"></div>
</div>
#contain{
display:flex
}
#left{
width: 200px;
height: 100px
}
#right{
flex: 1
height: 200px
}
scoped样式隔离原理
- 唯一选择器
1.当Vue编辑单文件组件时,在样式中使用scoped特性或module特性时,Vue会为每个样式选择器生成一个唯一的属性选择器。类似于[data-xxxxxx] - 编译时转换
1.Vue在编译过程中会解析单文件组件的模板,并对样式进行处理。对于具有scoped特性的样式,Vue会将选择器转换为带有唯一属性选择器的形式。对于module特性的样式,Vue会为每个选择器生成一个唯一的类名,并将类名与元素关联起来。 - 渲染时应用
1.在组件渲染过程中,Vue会为组件的根元素添加一个属性值为唯一标识符的属性,例如data-v-xxxxx。当组件渲染完成后,样式选择器中的唯一属性选择器或唯一类名将于组件根元素的属性匹配,从而实现样式的隔离。这样,只有具有相同属性值的元素才会应用相应的样式,避免了样式冲突和泄漏。
seo如何提高网站自然排名
- 关键字
- 内容优化
- 优化网站结构
- 高质量的外部链接
- 优化社交媒体
- 移动优化
SPA为什么会出现白屏,怎么优化
- SPA(single page web application):就是只有一张web页面的应用,是加载单个HTML页面并在用户与应用程序交互时动态更新该页面的Web应用程序
- 编译错误:检查代码语法错误。
- 依赖项问题:如果某个依赖项未正确配置或加载,可能也会导致白屏。
- 路由配置错误 :确保路由配置正确
- 组件未正确注册:
- 数据获取失败
- 缓存问题
webpack如何进行代码分割
- 使用import()函数:通过使用import()函数动态地引入模板,webpack会根据这些动态导入语句自动进行代码分割
- 使用optimization.splitChunks配置选项:该选项可以指定哪些模块应该进行代码分割,以及如何命名分割后的文件
- 使用require.ensure:在早期版本的webpack中,可以使用require.ensure方法进行代码分割
网站安全攻防:防范SQL注入与XSS攻击
- SQL注入攻击:是一种利用输入验证漏洞,将恶意SQL代码插入到数据库查询中的攻击方式。攻击者利用用户输入获取敏感信息,如密码‘用户数据或系统配置。防范的关键在于实施严格的输入验证和参数化查询。
- XSS(Cross-Site Scripting)在网页中植入恶意脚本,当用户浏览含有脚本的页面时,脚本在用户的浏览器上执行,窃取用户信息或控制用户的会话
1.对输出内容进行适当的编码,如HTML实体编码,阻止脚本标签的显示
2.使用Content Security Policy(CSP) 来限制网页可以加载的内容来源
3.采用HTTP-only cookies,防止JavaScript访问用户信息
4.强制HTTPS,确保数据传输的安全性
TCP三次握手和四次挥手
- 三次握手
1.客户端向服务端发送包含自身初始序号x的同文报文,进入SYN-SENT状态
2.服务端收到连接请求报文段后,会将连接放入半连接队列中,并向客户端发送包含自身初始序号y的同步确认报文,进入SYN-RECEIVED状态
3.客户端收到应答,向服务端发送确认报文,进入ESTABLISHED状态,此时成功建立长连接 - 四次挥手
1.客户端数据发送完毕,向服务端发送终止报文请求释放连接
2.服务器收到连接释放请求,告诉应用层释放TCP连接。然后发送确认报文,进入CLOSE-WAIT状态。此时表明客户端到服务端的连接已经释放,不再接收客户端的数据。但因为TCP是全双工的,所以服务器仍可以发送数据。
3.当服务器数据发送完毕,向客户端发送终止报文,发送连接释放请求,进入LAST-ACK状态
4.客户端收到连接释放请求,向服务端发送确认报文,此时客户端进入TIME-WAIT状态,会等待2MSL,若期间没有收到服务端的数据报文,进入CLOSED状态。服务器在收到确认应答后也进入CLOSED状态
TCP为什么是三次握手
- TCP通信需要确保双方都具有数据研发的能力
- 两次不安全:第一次带有SYN的ACK向客户端表明了服务端的收发能力,同时也验证了客户端自己的收发能力
- 第二次的ACK则向服务端表明了客户端的收发能力,同时也验证了服务端自己的收发能力
TCP三次握手哪次可以携带数据
- 第三次可以携带数据
- 如果第一条同步报文可以携带数据,当有人恶意攻击服务器时,就可以在第一次握手中携带大量额外数据来攻击服务器缓存
-第二次握手由服务器发起,服务器作为被动连接方,没有必要携带数据
给你十万条数据,怎么样顺滑的渲染出来?
- 虚拟列表
- 懒加载-滚动到底部加载
Promise.all 、Promise.race、Promise.allSettled、Promise.any的区别
共同点:都是处理批量异步请求的
- Promise.all()批量处理多个请求,返回的是所有请求结果组成的数组,这前提是所有请求成功,若其中一个失败,就抛出第一个rejected异常,不再继续往下执行
- Promise.allSettled()批量处理请求,无论结果是成功或失败,都继续向下执行;执行完毕,输出的是包含promise状态的数组对象、reject也不会走catch、
- Promise.any()批量处理请求,当请求中有一个状态为fullfilled时,就返回fullfilled状态的回调函数结果;当结果有多个状态为fullfilled的,就返回第一个fullfilled专业的回调函数结果;当所有请求结果状态为rejected。返回AggregateError错误
- Promise.race()批量处理多个请求,哪个结果先执行完,就输出哪个,无论结果是成功还是失败
- Promise.all()和Promise.allSettled()都是返回结果数组,而all只有请求全部成功才返回,allSettled()不论成功和失败都返回
- Promise.all()遇到错误就停止,Promise.allSettled()无论如何执行完
- Promise.any()返回第一个成功的回调函数运行结果;Promise.race()返回第一个回调函数运行结果,无论成功还是失败
ES6新增特性
- let和const关键字
- 箭头函数
- 类(Classes)
- 模板字符串
- 解构赋值
- 扩展运算符
- 默认参数
- 新的集合类型(如Map和Set)
- Symbol
ES6新增数据类型,以及用法
- Set集合:常用于去重
- Map:由于对象键值只能是字符串,不可以是对象类型,使用map可以避免键值必须为字符串的的限制,其键值可以为对象、数组等
- Symbol:在使用相同字符串对对象属性名或方法进行命名时会发生命名冲突,而使用symbol产生的名字是不同的
Flex布局的gap属性
- gap属性在Flex布局中用于定于Flex容器内部各项之间的间隙。
- 当只设置一个值时,这个值将应用于所有方向(即行和列)
- 当设置多个值时,第一个值应用于行间距,第二个值应用于列间距
大批量接口请求的前端优化
- 批量请求合并
- 请求防抖与节流
- 使用Web Workers:Web Workers允许在后台线程中运行JavaScript,从而不阻塞主线程。(针对于计算密集型或大量数据处理的请求)
- 缓存请求结果:对于不经常变化的数据,可以考虑在前端进行缓存
- 请求分布与懒加载:对于大量数据的展示,采用分页和懒加载可以显著减少初始加载时的请求量和响应时间。
假如有几十个请求,如何去控制并发?
利用Promise模拟任务队列,从而实现请求池效果
- Promise.all
- Promise.race
- async await
- 手动控制计数器
function getData() {
const limit = 5; // maximum concurrent requests
const dataUrls = ['https://example.com/data1.json',
'https://example.com/data2.json',
'https://example.com/data3.json',
'https://example.com/data4.json',
'https://example.com/data5.json',
'https://example.com/data6.json'];
let counter = 0;
const getDataPromise = dataUrl => {
return new Promise((resolve, reject) => {
fetch(dataUrl)
.then(response => {
counter--;
resolve(response);
})
.catch(error => {
counter--;
reject(error);
});
});
};
const getDataPromises = dataUrls.map(dataUrl => {
if (counter < limit) {
counter++;
return getDataPromise(dataUrl);
} else {
return new Promise(resolve => {
const interval = setInterval(() => {
if (counter < limit) {
counter++;
clearInterval(interval);
resolve(getDataPromise(dataUrl));
}
}, 100);
});
}
});
Promise.all(getDataPromises)
.then(responses => {
for (const response of responses) {
// handle each response here
}
})
.catch(error => {
console.error(error);
});
}
getData();
将数组 按照一定长度length去轮巡;循环打印同length的数组;比如数组为[1,2,3,4,5,6],每隔一秒打印[1,2,3,4]、[5,6,1,2]、[3,4,5,6]、[1,2,3,4]以此类推
var initArr = [1,2,3,4,5,6],len = 4
let cc = initArr.splice(0, len)
initArr = [...initArr, ...cc]
function Newarr(arr,len){
let a = arr; //原数组
let b = arr.splice(0, len);
let c = [...a, ...b];
return c;
}
console.log(cc)
setInterval(()=> {
let cc = initArr.slice(0, len)
initArr = Newarr(initArr, len)
console.log(cc)
}, 1000)
利用splice()会改变原数组、slice()方法不会改变原数组的特性实现
v-show和v-if的区别??
- v-show只是控制元素的显示,当值为false时,他的样式显示为display:none;v-show更加节省性能上的开销。
- v-if控制的是dom节点的存在与否。如果运行条件很少改变时,使用v-if较好。
- 如果需要非常频繁的切换,则使用v-show,如果在运行时条件很少改变,则使用 v-if 较好。
- 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级
关于作用域
- 除函数外,JS是没有块级作用域的
- 作用域链:就近原则:内部可以访问外部的变量;外部不可以访问内部
- var a=b=10; b指的是全局的window
- var声明的变量有变量提升
- 本层作用域有没有此变量【注意变量提升】
- JS除了函数外没有块级作用域
作用域链的作用
- 保证执行环境里有权访问的变量和函数是有序的
- 函数内部可以访问到函数外部声明的变量
- 函数外部访问不到函数内部的变量
什么是闭包?什么情况下会使用到闭包?
- 函数是可以访问上一层函数作用域变量,即便上一层函数已经关闭
- 使用闭包
- 使用闭包的情况:
1.通过循环给页面上的多个dom绑定事件。
2.把一些不希望暴露在全局的变量变成私有变量。
3.延续局部变量的寿命。
Vue和React的区别是什么?各自有什么优势?
- 数据绑定:Vue使用的是可变的数据(通过getter和setter监听数据的变化)。React强调的数据的不可变(通过setState监听数据的变化)
- 数据流:Vue是双向绑定。React是单向的。
- 模版渲染方式:Vue是通过扩展html语法进行渲染,React是通过JSX渲染模版。
keep-alive有什么作用
- keep-alive是vue的内置组件;
- 主要用于缓存组件实例,在多个组件动态切换时,避免组件的反复创建和渲染,从而有效提升系统性能;
- 使用方法用标签包裹动态组件,使用时会缓存不活动的组件实例,而不是销毁他们;
- include属性决定哪些组件可以被缓存,exclude属性决定哪些组件不会被缓存;
- keep-alive其内部所嵌套的组件都具有activated和deactivated生命周期函数;即在组件激活和失活的时候触发,activated在mounted后触发;
Vue3相比Vue2有哪些改进
- 使用来Compostion API,提高了代码逻辑的可复用性;
- 更好的TypeScript支持
- 引入了Fragment,允许组件有多个根节点;
- 使用了更小的包体积和更高效的运行时性能;
- Teleport组件允许将子组件渲染到DOM中的任何位置
- 提供了Suspense组件,用于处理异步组件的加载状态;
Vue3的Composition API是什么
- Composition API是一组新的、基于函数的API,它允许你以更灵活和可复用的方式来组织组件逻辑;它主要包括ref、reactive、computed、setup、watch等函数和钩子;
setup()函数在Vue3中起什么作用
- setup()是Vue3组件选项API的一个新选项;
- 它是Compostion API的入口点,在组件被创建之前执行;
- 用于初始化状态、计算属性和方法,并返回在模版中使用的响应式引用;
ref和reactive的区别
- ref用于创建简单的响应式引用,通常用于基本数据类型
- reactive用于创建响应式对象,通常用于复杂数据类型如数组和对象;
Vue3的响应式系统是如何工作的
- 当一个响应式对象被访问时,Vue3会通过Proxy拦截器捕获该访问,然后建立一个依赖关系,将该访问与正在访问的组件关联起来;
- 当响应式对象的属性发生改变时,Proxy拦截器会被触发,通知相关组件进行更新;
Vue 3 移除了哪些特性
- 过滤器filter;使用computed和函数代替;
- .native .sync 修饰符
- $listeners
- EventBus 的相关属性:on,off 和 $once
- $children,使用 ref 代替
当数据改变时,Vue是如何更新DOM的(DIff算法和虚拟DOM)
- 当我们修改某个数据时,如果直接重新渲染到真实DOM,开销是很大的;
- 当数据发生改变时,Observer会通知所有watcher,watcher就会调用patch方法(Diff的具体实现),把变化的内容更新到真实DOM,俗称打补丁;
谈谈对Vue的理解
- Vue是一种用于构建用户界面的渐进式JavaScript框架。核心思想是将应用程序拆分成多个可复用的组件,每个组件负责自己的功能和样式,然后通过组合这些组件来构建整个应用程序
Vue 的特点
- 响应式数据绑定:双向数据绑定的概念,当数据发生变化时,页面会自动更新,无需手动操作DOM;
- 组件化开发:Vue将页面拆分为多个独立的组件,每个组件都有自己的模板、样式和逻辑,可以实现组件的复用,提高开发效率;
- 虚拟DOM:Vue使用虚拟DOM技术来高效的更新和渲染页面,只需更新变化的部分,减少了对真实DOM的操作,提高了性能;
- 生态系统的丰富:Vue拥有完整的工具链,
如何区分深拷贝和浅拷贝?怎么实现深拷贝?
- 浅拷贝就是增加了一个指针指向已存在的内存地址。
- 深拷贝就是增加一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
实现深拷贝的方式
- JSON方法实现
- 使用for…in实现遍历和复制
- 利用数组的Array.prototype.forEach
- 浅拷贝(使用object.assign方法)
VUE props数据流向
- 单向绑定数据流,props
Vue组件的传值的方法
- 父组件–>子组件:
- props:子组件不能修改父组件的数据
- $children获取子组件和父组件对象:父组件直接修改子组件的数据
- $ref获取指定的子组件:父组件直接修改子组件的数据
- provide/inject:父组件直接向某个后代组件传值
- 子组件–>父组件:
- 使用$emit传递。
- 使用$parent.获取父组件对象,然后再获取数据对象:子组件可以直接修改父组件的数据
- 非父子组件间传值
- 事件总线(建立一个公共的js文件,专门用来传递消息)eventBus
- $sttrs/listeners
- vuex
Vue中的slot插槽
- 匿名插槽:没有名字
- 具名插槽:有名字
- 作用域插槽:可以传值
如何封装组件
- 组件稍微复杂的、需要涉及到组件通信、插槽slot、、、
浏览器的内核有哪些?
- Trident内核
- Webkit内核
- Gecko内核
- Presto内核
Promise是什么
他的主要作用是用来解决JS异步机制的,回掉机制产生的“回掉地狱”。
- Promises是ES6引入的异步编程的处理方案,有三种状态:pending(进行中)、resolved(已完成)、rejected(已失败);
- Promise是一个构造函数,可以实例化对象。封装异步操作,获取成功和失败的结果
Promise和async await的区别
- 两者都是做异步处理的,使异步转为同步,目的都是为了解决异步回调产生的“回调地狱”
- Promise是一个表示异步操作最终完成(或失败)及其结果的对象,他有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败);async/await是基于Promise的语法糖,他让异步代码看起来和同步代码很相似;
- Promise使用then()和catch()方法来处理异步操作的结果和错误;async/await使用async和await关键字编写异步代码;
- Promise使用catch()方法来捕获错误;而async/await使用try-catch语句来捕获错误;
- Promise不会阻塞主线程;async/await是不会阻塞,会阻塞的只是使用await的函数内部;
Promise优缺点
- 优点:支持链式调用,可以解决回调地狱的问题;指定回调函数的方式更加灵活;
- 缺点:无法取消Promise;当前pending状态无法知道进展;如果不设置回调函数,Promise内部抛出的错误不会反应到外部;
- 特点:只有异步操作的结果,可以决定当前是哪一种状态,任何其余操作都无法改变这个状态
Promise构造函数是同步的,Promise.then()是异步的
Promise 对象的状态只能被转移一次,resolve(‘success1’) 时状态转移到了 fullfilled 。后面 reject 就调用无效了,因为状态已经不是 pending
CSS的样式优先级
!important > 内联样式 > ID > Class 、伪类、属性选择器 > 标签名、伪元素
Vue中的data为什么是一个函数,不是一个对象?
- 对象是引用类型,组件可能会被多个实例同时引用。
- 如果data值为对象,将导致多个实例共享一个对象,其中一个组件改变data属性值,其他实例也会受到影响。一个数据改变了其他也改变了。所有实例的data是一样的。
- data是一个函数时,每个组件实例都有自己的作用域,return一个新对象,就相当于声明了新的变量,相互独立。
Vue中的将数据定义在data的return内和return外的区别
- return内:是可以修改的
- return外:不可以修改,没有get和set
import和require有哪些区别?
- require是运行时动态加载,import是静态编译
- require输出的是一个值的拷贝,import输出的是一个值的引用
exports和module.exports的区别
- exports和module.exports是指向同一个内存的。
- exports是module的一个属性
- module.exports导出的是整个模块,exports导出的是一个对象
export和export default的区别
- 两者均可用于导出常量,函数,文件,模块等。
- 使用export做导出时,在导入时要加 {},export default不需要
- 使用export做导出时,在导入时要加 {}并且要使用导出的函数或者对象名
- 在同一个模块中,export可以存在多个,但是export default仅存在一个。
Vue的双向绑定原理是什么??响应式原理
- 实现一个监听器Observer,用来劫持并监听所有属性,如果有变动,就通知订阅者。
- 实现一个订阅者Watcher,可以受到属性的变化通知并执行相应的函数,从而更新视图。
- 实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模版数据以及初始化相应的订阅器
- 采用数据劫持结合发布者-订阅者的模式,通过Object.defineProperty()来劫持各个属性的setter个getter,在数据变动时通知订阅者,触发相应监听回调;
Vue的单向数据流原理是什么??
- 单向数据流是基于依赖追踪的,即子组件依赖于其父组件,而父组件不依赖于子组件的数据。这样,数据只能从父组件流向子组件,从而确保数据的一致性和可追溯性
Vue的v-model
- 本质是一个语法糖 通过props传递value 通过$emit监听input事件
实现响应式布局的方法
- 为了网页能够兼容不同的终端,所以要响应式布局。
- 设置meta标签,禁止用户缩放
- 通过媒介查询来设置样式
- 设置字体,rem是相对于根元素。之前先重置根元素的大小
- 宽度不固定,设置百分比
CSS元素的类型有哪些?
- 块元素-div h1-h6 ul li ol
- 行内元素-a img select input
- 行内块元素-
js数据类型
- 原始数据类型:null undefined String Number Boolean Symbol bigInt
- 引用数据类型:Arrary Object Function Date RegExp
null和undefined区别
- null的数据类型是object;undefined的数据类型是undefined
- nul l== undefinded null !== undefined
- null代表空 空指针;undefinded代表定义了没有赋值
- null转为数字的值是0 undefined转为数字的值是NaN
= =和= = =区别
- ==比较的值
- ===比较值和类型
vue-router怎么定义动态路由?怎么获取动态参数??
- 动态路由的创建:使用path属性过程中,使用动态路径参数,以冒号开头
- 通过this.$router.params获取动态参数
清除浮动的方式??
- 父级元素添加overflow:hidden;
- 添加额外标签,并且在标签内使用clear:both;
- 给浮动元素父级设置高度;
- 使用伪元素(必须是块级元素)(content必须为空,height必须为0)
clearfix:after {
content: '';
height: 0;
display: block;
clear: both;
overflow: hidden;
visibility: hidden;
}
.clearfix {
zoom: 1;
}
- 使用双伪元素清除浮动
.clearfix:before,.clearfix:after {
content: "";
display: block;
clear: both;
}
.clearfix {
zoom: 1;
}
split() splice()和join()的区别
- join()方法是将数组中所有元素放入字符串
- split()方法是把一个字符串分割成字符串数组
- splice()方法向\从数组中添加\删除项目,返回删除的项目。该方法会改变原数组。
js的本地对象,内置对象和宿主对象?
- 本地对象:Object Function Arrary
- 内置对象:Math和Global,内置对象是本地对象的一种
- 宿主对象:所有的BOM对象和DOM对象都是宿主对象
cookies,sessionStorage和localStorage的区别?
- cookies会发送到服务器端,有数据大小限制为4k,有效值在过期时间之前一直有效。
- sessionStorage数据大小限制比cookies大的多,浏览器关闭就删除数据。
- localStorage是持久性存储,数据大小限制比cookies大的,浏览器关闭不会删除数据除非主动删除。
let和const的区别
相同点:
- 只在声明的块级作用域内有效
- 不存在变量提升
- 不可重复声明
不同点:
- let声明的变量的值,类型可以改变,const声明的常量不可以改变
for…in 和for…of的区别
- for…in遍历的是数组的下标
- for…of遍历的是数组的值
css的加号选择器
- css的加号选择器就是对找到的某类元素除第一个元素以外的兄弟起作用,即第一个元素不起作用,后面的兄弟元素都会起作用
ajax的工作原理
- 创建ajax对象(XmlHttpRequest)
- 判断数据传输方式(get/post)
- 打开链接open()
- 发送send()
- onreadystatechange数据接收完成,判断http响应状态(status)200-300之间或者304(缓存)执行回调函数
get和post的区别
- get传递数据是通过地址栏url进行传递的,是可以直接看到get传递的参数。post传参方式是不可见的。
- get传递的数据长度是受到url大小的限制,URL最大长度是2048个字符。post没有长度限制。
- get后退不会有影响,post后退会重新进行提交
- get请求可以被缓存,post不可以缓存
- get请求只URL编码,post支持多种编码方式
- get请求的记录会留在历史记录中,post请求不会留在历史记录
ajax的优缺点
优点
- 局部刷新页面,提升用户体验
- 按需取数据,减少冗余请求
- 基于xml标准化,并被广泛支持,不需要安装插件
缺点 - ajax大量的使用js和ajax,取决于浏览器的支持,需要考虑对浏览器的兼容性。
- ajax只是局部刷新,所以页面的后退按钮是没有用的
- 对流媒体还有移动设备的支持不是太好
对js面向对象的理解
- 面向对象的三大原则:封装,继承,多态、
封装—把客观事物封装成抽象的类,隐藏属性和方法的实现细节,仅对外公开接口
- 通过构造函数添加
- 通过原型prototype
- 在类的外部添加
继承
- 原型链继承
- 组合式继承
多态—就是执行同一操作且作用与不同对象时返回不同的结果
new操作符具体做了什么
- 创建了一个空的对象,var obj=new Object()
- 让空对象的原型指向构造函数的原型,obj.proto=Func.prototype;
- 将空对象作为构造函数的上下文(改变this的指向),并执行var result = Func.call(obj)
- 对构造函数返回值的处理判断:判断返回类型,如果是基本类型就忽略,如果是引用类型,就返回引用类型
call、apply、bind的区别
- 都可以用来改变this指向
- callh和apply都会立即执行;bind不会,bind返回的是函数;需要加入()
- apply的第二个参数是数组,call和bind接受多个参数
- apply:Math.max.apply(null, arr)
画一个三角形
.a{
width:0;
height:0;
border-left:10px solid transparent;
border-right:10px solid transparent;
border-bottom:10px solid red;
}
事件委托和事件绑定的区别
- 事件绑定:把事件绑定在dom上,当DOM节点被选择,将事件与之绑定。
- 事件委托:把目标元素绑定到父元素上,利用冒泡机制
css动画实现的方法
- 过度动画(tansition)
- animation动画
箭头函数和普通函数的区别
- 普通函数的this指向调用他的那个对象
- 箭头函数的this永远指向其上下文的this,任何方法都改变不了他的指向,call,apply都不行
$ route和$ router的区别
- $ route是当前路由的一个对象。比如:$route.path
- $ router的是整个路由的属性和方法
导航守卫
- 全局守卫
- 路由独享守卫
- 组件内守卫
- 权限验证 如果是登录状态就进入到页面 如果不是就跳回到登录页
event.stopPropagation(),event.preventDefault()和return false的区别
- event.stopPropagation():阻止事件的冒泡方法,不让事件向document蔓延,但是默认事件仍然会执行,当你调用这个方法的时候,如果点击一个连接,这个连接仍然会被打开,
- event.preventDefault():阻止事件的默认方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;
- return false:同时阻止事件冒泡和事件默认,写上此代码,连接不会被打开,事件也不会传递到上一层的父元素;可以理解为return false就等于同时调用了event.stopPropagation()和event.preventDefault()
filter和map的区别
- 相同点:不会改变原数组,不会对空数组进行检测
- 不同点:filter是满足条件的留下,是对原数组的过滤,map是原数组的加工,映射成一一对应的新数组
什么是TypeScript
- TS是JS的超集,可以被编译成JavaScript代码;
- 用JS编写的合法代码在TS中依然有效;
- TS给JS添加了可选的静态类型和基于类的面向对象编程;如类、接口、继承、泛型等
TypeScript 的特性
- 类型批注:通过类型批注提供在编译时启动类型检查的静态类型;
- 类型推断:TS中没有批注变量类型会自动推断变量的类型;
- 类型擦除:在编译过程中批注的内容和接口会在运行时利用工具擦除;
- 接口:TS中用接口定义对象类型;
- 枚举:用于取值被限定在一定范围内的场景;
- Mixin:可以接受任意类型的值;
- 泛型:写代码时使用一些指定类型
- 命名空间:名字只在该区域内有效,其他区域可重复使用该名字而不冲突;
- 元组:元组合并了不同类型的对象,相当于一个可以装不同类型数据的数组
TypeScript 和 JavaScript的区别
- TS是一种面向对象编程语言,JS是一种脚本语言(尽管JS是基于对象的)
- TS支持可选参数,JS不支持该特性
- TS支持静态类型,JS不支持
- TS支持接口,JS不支持接口
类型声明和类型推断的区别
- 类型声明是显式的为变量或函数指定类型,
- 类型推断是TS根据赋值语句右侧的值自动推断变量的类型;
说说TypeScript 的数据类型有哪些?
- boolean:let flag:boolean = true;
- number:let nun:number = 12
- string:let str:string = ‘sss’
- array:let arr:Array = [12,2]
- tuple(元组类型):let tupleArr:[number, string, boolean]
- enum(枚举类型):enum Color { Red, Green, Blue }
- any(任意类型):let num:any = 12
- null和undefined:let num:number|undefined
- void:标识方法返回值的类型,表示该方法没有返回值
- never:是其他类型的子类型,可以赋值给任何类型,代表从不会出现的值,但是没有类型是never的子类型,声明never的变量只能被never类型所赋值
- object:ler obj:object
说说对TypeScript 中枚举类型的理解?应用场景?
- 枚举是一个被命名的整型常数的集合,用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将他定义为枚举类型;
- 枚举就是一个对象的所有可能取值的集合
- 比如:后端返回的字段使用0~6标记对应的日期,这时候用枚举定义日期
说说对TypeScript 中接口的理解?应用场景?
- 接口用于描述对象的形状的结构化类型;
- 它定义了对象应该包含哪些属性和方法;
- 在TS中,接口可以用来约束对象的结构,提高代码的可读性和维护性;
接口(interface)和类型别名(type)的区别
- 都是用于定义类型的强大工具
- interface可以继承 extends ;type不能继承,只能交叉类型&
- interface重名会合并属性,type不会合并
- interface不能在外面定义联合类型
说说对TypeScript 中类的理解?应用场景?
- 在TS中,类是用于创建对象的模板。一个类定义了对象的属性和方法,这些属性和方法称为类的成员;类的成员可以是字段(变量)、方法(函数)、构造函数、访问器(getter和setter)、索引签名和静态成员;
- TS的类支持面向对象编程的特性:封装、继承、多态、抽象类和接口
- 用于进行API设计、封装业务逻辑、代码冲用。。。
说说对TypeScript 中函数的理解?与JavaScript函数的区别?
- TS为JS函数添加了额外的功能,丰富了更多的应用场景
- TS声明函数需要定义参数类型或者声明返回值类型;
- TS在参数中,添加可选参数供使用者选择;
- TS增添函数重载功能:允许创建数项名称相同但输入输出类型或个数不同的子程序;
说说对TypeScript 中泛型的理解?应用场景?
- 泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型
- 定义函数、接口或者类的时候,不预先定义好具体的类型,而在使用的时候再指定类型的一种特性的时候,可使用泛型
说说对TypeScript 中高级类型的理解?有哪些?
- TS的高级类型是其类型系统中最强大和灵活的部分,他们允许开发者创建复杂和精细的类型定义;
- 交叉类型:通过&将多个类型合并为一个类型;
- 联合类型:联合类型的语法规则和逻辑“或”的符号一致 T | U
- 类型别名:使用type 关键字给类型起个新名字;
- 类型索引:keyof用于获取一个接口中Key的联合类型;
- 类型约束:通过extend 进行约束
- 条件约束:语法规则和三元表达式一样
说说对TypeScript 中装饰器的理解?应用场景?
- 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法、访问符、属性或参数上,是一种在不改变原类和使用继承的情况下,动态的扩展对象功能
TypeScript 变量的命名规则:
- 变量名称可以包含数字和字母
- 除了下划线_和美元符号$,不能包含其他特殊字符,包含空格
- 变量名不能以数字开头
- 声明变量的类型,但没有初始值,变量值会设置为 undefined:
- 声明变量并初始值,但不设置类型,该变量可以是任意类型:
- 声明变量没有设置类型和初始值,类型可以是任意类型,默认初始值为 undefined:
Number 对象属性
- MAX_VALUE:代表最大的数,MAX_VALUE 属性值接近于 1.79E+308。大于 MAX_VALUE 的值代表 “Infinity”。
- MIN_VALUE:代表最小的数,即最接近 0 的正数 (实际上不会变成 0)。最大的负数是 -MIN_VALUE,MIN_VALUE 的值约为 5e-324。小于 MIN_VALUE (“underflow values”) 的值将会转换为 0。
- NaN:非数字值
- NEGATIVE_INFINITY:负无穷大,溢出时返回该值。该值小于 MIN_VALUE
- POSITIVE_INFINITY:正无穷大,溢出时返回该值。该值大于 MAX_VALUE。
- prototype:Number 对象的静态属性。使您有能力向对象添加属性和方法。
- constructor:返回对创建此对象的 Number 函数的引用。
Number 对象方法
-
toExponential():把对象的值转换为指数计数法。
var num1 = 1225.30
var val = num1.toExponential();
console.log(val) //: 1.2253e+3
- toFixed():把数字转换为字符串,并对小数点指定位数。
var num3 = 177.234
console.log("num3.toFixed() 为 "+num3.toFixed()) // 输出:177
console.log("num3.toFixed(2) 为 "+num3.toFixed(2)) // 输出:177.23
console.log("num3.toFixed(6) 为 "+num3.toFixed(6)) // 输出:177.234000
- toLocaleString():把数字转换为字符串,使用本地数字格式顺序。
var num = new Number(177.1234);
console.log( num.toLocaleString()); // 输出:177.1234
- toPrecision():把数字格式化为指定的长度。
var num = new Number(7.123456);
console.log(num.toPrecision()); // 输出:7.123456
console.log(num.toPrecision(1)); // 输出:7
console.log(num.toPrecision(2)); // 输出:7.1
- toString():把数字转换为字符串,使用指定的基数。数字的基数是 2 ~ 36 之间的整数。若省略该参数,则使用基数 10。
var num = new Number(10);
console.log(num.toString()); // 输出10进制:10
console.log(num.toString(2)); // 输出2进制:1010
console.log(num.toString(8)); // 输出8进制:12
- valueOf():返回一个 Number 对象的原始数字值。
var num = new Number(10);
console.log(num.valueOf()); // 输出:10
数组的哪些方法不会改变原数组
- every()方法不会改变,监测数组每一项是否符合条件,返回true or false
- filter()方法不会改变,监测数值元素,返回符合条件的所有元素的数组
- join不会改变,将数组中的每一项放进一个字符串
- lastIndexOf()不会改变,返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索
- map()不会改变.通过指定函数处理数组的每个元素,并返回处理后的数组
- pop()会改变,删除数组的最后一个元素并返回删除的元素。
- push()会改变,向数组的末尾添加一个或多个元素,并返回新的长度
- reduce()不会改变
- reverse()会改变
- shift()会改变,删除并返回数组中的第一个元素
- slice()不会改变,返回的是一个新数组
- some()不会改变,检测数组元素中是否有元素符合指定条件。
- sort()不会改变‘‘
- splice()会改变 . 从数组中添加或删除元素。
- unshift()会改变,向数组的开头添加一个或更多元素,并返回新的长度。
TypeScript 的类的继承
- 子类不能继承父类的私有成员(方法和属性)和构造函数。其他都可以继承
- 子类只能继承一个父类,但支持多重继承
- super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。
- static 关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用
一个页面中设置了只作用于当前组件的样式scoped 时,怎么修改或者是覆盖element-ui 的样式
可以使用深度选择器
有三种方式:
20. 如果vue文件使用的是css 那么 可使用 >>>
21. 如果vue文件使用的是scss 那么可使用 /deep/ ,但是 在用vue-cli3编译时,/deep/会报错或者警告
22. 如果vue文件使用的是scss 那么可使用 ::v-deep 编译方式更快 更保险
this的指向
在js中,this是函数当前的运行环境,它表示当前对象的一个引用;this永远指向它所在函数的实际调用者,如果没有调用者,就指向全局对象,ES5之后严格模式下值为undefined
- 默认绑定规则:默认指向window,函数独立调用时指向全局对象
- 隐式绑定规则:谁调用就指向谁(通过对象.函数属性()方式调用,函数中的this指向该对象)this是在执行函数时才确定的
当对象链式调用时,this指向最靠近函数的对象
共享实例prototype的this指向调用它的实例对象
事件绑定和监听函数(非箭头函数)中,this指向被绑定/监听的元素对象
内联事件中this指向
a 内联处理函数调用代码时,this指向监听器对应的DOM元素
b 代码被包含在函数内部执行(直接调用)时,非严格模式指向全局对象window,严格模式指向undefined
c 回调函数中(定时函数内部的回调函数,forEach,sort等)this默认指向全局对象window
webpack打包原理
webpack打包原理是根据文件间的依赖关系对其进行静态分析,将这些模块按照指定规则生成静态资源,当webpack处理程序时,他会递归的构建一个依赖关系图,其中包含应用程序需要的每个模块,将这些模块打包成一个或者多个bundle
webpack 打包流程
- 读取入口文件
- 分析入口文件(AST)得到其所依赖的文件信息
- 递归读取每个文件的依赖信息,生成AST树,得到关系依赖图
- 代码转化,生成ES5代码
webpack 有哪些模块
- Entry:入口起点指示webpack应该使用哪个模块,来作为构建其内部依赖图的开始
- Output: 指示webpack在哪里输出他所创建的buldles,以及如何命名这些文件,默认值为 ./dist
- Module:在webpack一切皆模块,一个模块对应一个文件,webpack会从配置的Entry开始递归找出所有依赖的模块
- Chunk:代码块,一个Chunk由多个模块组合而成,用于代码合并与分割
- Loader:loader可以将所有文件类型转换为webpack能够处理的有效模块,然后可以利用webpack的打包能力,对他们进行处理,本质上,webpack loader将所有类型的文件转换为应用程序的依赖图(和最终的bundle)可以直接引用的模块
- Plugins:loader被用于转换某些类型的模块,而plugins(插件)用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量,
webpack 的优势
- webpack是以CommonJS的形式来书写脚本的,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移
- 能被模块化的不仅仅是JS
- 开发便捷,能替代部分 grunt/gulp 的工作 比如打包、’压缩混淆、图片转base64等
- 扩展性强。插件机制完善
webpack的核心机制(loader、plugins)
- loader是告诉webpack如何转换处理某一类型的文件,并且引入到打包出口的文件中
- plugind是用来自定义为webpack打包过程中的方式,一个插件是含有apply方法的一个对象,通过这个方法可以参与整个webpack打包的各个流程
什么是bundle,什么是chunk,什么是module:
- bundle是由webpack打包出来的文件
- chunnk是webpack在进行模块依赖分析的时候,代码分割的代码块
- module是开发中的单个模块
什么是模块热更新
模块热更新是webpack的一个功能,他可以使得代码修改后不用刷新浏览器就可以更新内容,是高级版的自动刷新浏览器,(将代码重新执行一遍而不是整体刷新浏览器)
微信小程序的生命周期
前台后台定义:当用户点击左上角关闭,或者按了设备Home键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入小程序或打开小程序,又会从后台进入前台
- 应用的生命周期
小程序的生命周期是在app.js里面调用的,通过App(Object)函数来注册一个小程序,指定其小程序的生命周期回调- onLaunch:小程序初始化完成时触发,全局只触发一次(监听小程序初始化)
- onShow:小程序启动时,或从后台进入前台显示,会触发onShow(监听小程序显示)
- onHide:小程序从前台进入后台,会触发onHide(监听小程序隐藏)
- onError:小程序发生脚本错误或API调用报错时触发
- onPageNotFound:小程序要打开的页面不存在时触发
- onUnhandledRejection:小程序有未处理的promise拒绝时触发
- onThemeChange:系统切换主题时触发
应用的生命周期执行过程
- 用户首次打开小程序,触发onLaunch(全局只触发一次) - 小程序初始化完成后,触发onShow(监听小程序的显示) - 小程序从前台进入后台,触发onHide方法 - 小程序从后台进入前台显示,触发onSHow - 小程序后台运行一段时间,或系统资源占用过高,会被销毁
- 页面的生命周期
页面的生命周期就是当你每进入/切换到一个新的页面时,就会调用的生命周期函数,同样通过App(Object)来注册一个页面- onLoad:监听页面的加载,一个页面只执行一次,参数可以获取wx.navigateTo和wx.redirectTo及中的 query
- onShow:监听页面的显示,执行多次。每次打开页面都会调用一次
- onReady:监听页面初次渲染完成,执行一次,代表页面已经准备妥当,可以和视图层进行交互
- onHide:监听页面的隐藏,当navigateTo或底部tab切换时调用
- onUnload:监听页面的卸载,redirectTo或navigateBack的时候调用
页面的生命周期执行过程
- 小程序注册完成后加载页面,触发onLoad - 页面载入后触发onShow,显示页面 - 首次显示页面,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次 - 当小程序后台运行或跳转到其他页面时,触发onHide方法 - 有小程序由后台进入前台运行或重新进入页面,触发onShow - 使用重定向方法 wx.redirectTo(OBJECT) 或关闭当前页返回上一页 wx.navigateBack(),触发 onUnload
切换页面时触发的生命周期
- 当首次加载A页面,A触发的生命周期为:Onload onShow Onready - 当A页面切换到B页面时,A页面触发OnHide B页面触发:Onload Onshow Onready - 当B页面返回到A页面时,触发onUnload, 当不清缓存时,再次进入A页面只触发Onshow
- 组件的生命周期
- created:监听页面加载 组件实例刚刚被创建好时触发 只用与给this添加自定义属性字段
- attached:监听页面显示 在组件实例完全初始化完毕、进入页面节点树后被触发 大多数初始化工作
- ready:监听页面初次渲染完成
- moved:监听页面隐藏
- detached:监听页面卸载
- error:每当组件发生错误抛出
微信小程序的应用生命周期和页面生命周期同时存在时 执行顺序
- 打开小程序:(App)Onlaunch (App)Onshow (Pages)Onload (Pages)Onshow (Pages)onReady
- 进入下一个页面:(Pages)OnHide (Next)Onload (Next)OnSHow (Next)OnReady
- 返回上一个页面:(curr)onUnload (Pre)OnShow
- 离开小程序:(App)OnHide
- 再次进入小程序:小程序未销毁 (App)Onshow 小城已销毁 (App)Onlaunch重新开始执行
微信小程序组件之间传值的方法
- 使用本地存储来传递数据 wx.setStorageSync 与 wx.getStorageSync
- 使用路由来传递数据
- 使用全局变量来传递数据 app.js 中的 globalData 将数据存储为全局变量,在需要使用的页面通过 getApp().globalData 获取
- 通过使用wx.navigateBack()返回之前的页面
let pages = getCurrentPages(); let prevPage = pages[pages.length - 2]; prevPage.setData({ data: this.data })
微信小程序 父子组件间通信
- 属性绑定 父传子
用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
在子组件的propertris定义好父组件传过来的数据 - 事件绑定 子传父
用于子组件向父组件传递数据,可以传递任意数据
子组件通过triggerEvent(‘父组件传递过来的自定义事件名称’,{携带参数})父组件在自定义函数里通过event 事件对象.detail来获取参数 - 获取组件实例
父组件还可以通过this.selectComponent()获取子组件实例对象,这样就可以访问子组件的任意数据和方法
微信小程序 全局状态管理
- 使用App()对象的globalData对象
- 自定义事件通信:wx. e m i t 和 w x . emit 和 wx. emit和wx.on
- redux
微信小程序 怎么跟随事件传值
在页面标签 通过绑定 dataset-key = value 然后绑定点击通过e.currentTarget.dataset.key 来获取标签上绑定的值
微信小程序 wxss 和 css 有什么区别
- 都是用来描述页面的样子
- wxss背景图片只能引入外链 不能使用本地图片
- wxss新增了尺寸单位,wxss在底层支持新的尺寸单位rpx 尺寸单位为 rpx , rpx 是响应式像素,可以根据屏幕宽度进行自适应
微信小程序 的双向绑定 和 vue 有什么不同
大体相同 ,但是小程序的this.data的属性是不可以同步到视图的,必须调用 this.setData()方法
怎么提高微信小程序的应用速度
- 提高页面的加载速度
- 用户行为预测
- 减少默认的data的大小
- 组件化方案
你是怎么封装微信小程序的数据请求
-
在根目录下创建util目录及api.js文件和apiConfig文件
-
在apiConfig.js文件封装基础的get、post、put和upload 等方法,设置请求体,带上token和异常处理等
-
在api中引入apiConfig.js封装好的请求方法,根据页面数据请求的urls,设置对应的方法并导出
-
在具体的页面中引入
或者 -
将所有的接口放在统一的js文件并导出
-
在app.js中创建封装请求数据
-
在子页面调用封装的请求数据
微信小程序和H5的区别
- 运行环境不同(小程序在微信中运行,h5在浏览器中运行)
- 开发成本不同(h5需要兼容不同的浏览器)
- 获取系统权限不同(系统级权限可以和小程序无缝衔接)
- 应用在生成环境的运行速度流程(h5需不断对项目优化来提高用户体验)
怎么解决微信小程序的异步请求问题
在回调函数中请求下一个组件的函数
小程序关联微信公众号如何确定用户的唯一性
使用wx.getUserInfo方法withCredentials为true时,可获取encryptedData,里面有union_id,后端需要进行对称解密
微信小程序的逻辑层和渲染层
- 小程序运行环境分为逻辑层和渲染层,其中WXML模板和WXSS样式工作在渲染层,js脚本工作在逻辑层
- 渲染层的页面使用了WebView进行渲染,一个小程序存在多个界面,所以渲染层存在多个WebView线程
- 逻辑层采用JsCore线程运行JS脚本
- 逻辑层:将数据进行处理后发送给视图层,同时受到视图层的事件反馈
- 渲染层:将逻辑层的数据反应成视图层,同时将视图层的事件发送给逻辑层
使用webview直接加载有什么注意事项
- 确认是否需要用户授权
- 确认webview的配置
- 遵守安全标准
- 确认webview的性能
- 避免webview内存泄漏
- 报账用户隐私
微信小程序实现分享功能的方法
- 在page.js中实现onShareAppMessage,便可在小程序右上角选择分享该页面
- 自定义按钮实现分享,在page中添加一个带有open-type=‘share’的button标签()
简述wx.navigateTo(),wx.redirectTo(),wx.switchTab(),wx.navigateBack(),wx.reLaunch()的区别?
- wx.navigateTo:用于保留当前页面,跳转到应用内某个页面,使用 wx.navigateBack可以返回到原页面。
- 对于页面不是特别多的小程序,通常推荐使用wx.navigateTo进行跳转,以便返回原页面,以提高加载速度,当页面特别多时,不推荐使用 - wx.redirectTo:用于关闭当前页面,跳转到应用内某个页面
- 可以避免跳转前页面占据运行内存,但返回时页面需要重新加载,增加了返回页面显示时间 - wx.reLaunch:实现从非tab bar 跳转到tab bar 或在 tab bar 间跳转,效果等同于 wx.switchTab。
- wx.relaunch先关闭了内存中所有保留的页面,在跳转到目标页面 - wx.switchTab:先关闭其他所有tabBar页面,跳转到tabBar页面。
- 跳转到 tab bar 页面 最好选择 wx.switchTab - wx.navigateBack:用于关闭当前页面,并返回上一页面或多级页面
- 开发者可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。这个 API 需要填写的参数只有 delta,表示要返回的页面数。若 delta 的取值大于现有可返回页面数时,则返回到用户进入小程序的第一个页面。当不填写 delta 的值时,就默认其为 1(注意,默认并非取 0),即返回上一页面。
小程序和vue的写法有什么不同呢
- 遍历的时候:vue 是 v-for 小程序是 wx:for
- 赋值的时候:小程序 是 this.data.item this.setData({item:1}) vue this.item this.item = 1
微信小程序授权登陆的流程
- 当用户进入小程序,首先需要判断用户是都授权过此小程序(wx.getSetting res.authSetting[‘scope.userInfo’])
- 如果没有授权,需要通过一个按钮来实现授权登录(当button组件的open-type=“getUserInfo” 并结合bindgetuserinfo事件,可以获取到用户信息(是否授权)
- 通过bindgetuserinfo事件,我们可以获取到个人的信息、加密偏移数据、加密用户信息(e.detail)
- 用户可以授权登陆 也可以取消登陆
- 根据登陆接口返回的code码,来判断是否是新用户
- 在用户注册成功后,再调登陆接口,保存token,在有些页面需要使用token
- 在步骤1中,当授权过时,需要查看token是否存在
- 当token存在,直接执行逻辑代码
- token不存在,就需要登陆,登陆后判断返回的code码。再根据code码判断用户是否是新用户,最后保存token
vue的生命周期
- 创建前(beforeCreate):组件实例创建之初,无法获取生效的实例属性
- vue的实例挂载对象$el和data都为undefined,还未被初始化。 - 创建后(Created):组件实例创建完毕
- 如果要操作data中的数据或者调用methods方法最早可以在created执行,$el还没有 - 载入前(beforeMount):节点挂载开始时调用;render函数第一次被调用
- vue的实例$el和data已经初始化好了,但还是挂载之前的虚拟DOM节点,data.messgae还未被替换, - 载入后(Mounted):完成实际节点的渲染
- 更新前(beforeUpdate):组件数据更新前,虚拟节点生成
- 更新后(Updated):数据更新完成,生成实际节点
- 销毁前(beforeDestory):vue从运行阶段进入销毁阶段,这个时候上左右我的data method 。。都还可以用,还没有真正被销毁
- 销毁后(destoryed): 组件已经完全被销毁
- keep-alive:
- activited:被激活
- deactivated:被销毁
父子组件嵌套下的生命周期顺序是什么
- 加载渲染过程:
- 父beforeCreate > 父created >
- 父bedoreMount >
- 子beforeCreate > 子created >
- 子breforeMount > 子mounted >
- 父mounted
- 更新过程:
- 父beforeUpdate >
- 子beforeUpdate > 子updated >
- 父updated
- 销毁过程:
- 父beforeDestory >
- 子beforeDestory > 子destoryed >
- 父destoryed
加入keep-alive会执行哪些生命周期
- 会增加activated和deactivated两个生命周期
- 当组件添加了keep-alive,第一次进入组件会执行:beforeCreate created beforeMount mounted activated
第二次或者第N次进入组件会执行哪些生命周期
- 如果添加了keep-alive,执行:activated,
- 如果没有添加keep-alive,执行:beforeCreate created beforeMount mounted
created 和 mounted 的区别
- created:在模板渲染前HTML前调用,即通常初始化某些属性值,然后再渲染成视图
- mounted:在模板渲染前HTML后调用,通常是初始化页面完成后,再对HTML中的DOM做一下操作
为什么发送请求不在beforeCreate里面
- 如果请求在methods中封装好的,在beforeCreate中调用的时候,beforeCreate阶段是获取不到methods里面的方法(会报错)
- beforeCreate阶段实例挂载对象$el和data都是undefined
- created阶段可以获取到data以及methods里面的方法
发送请求是在created 还是mounted
- 具体要看项目和业务的情况;
- 由于父子组件的执行顺序:先执行父组件的 breforeCreate created beforeMount 再执行 子组件的 breforeCreate created beforeMount mounted 最后执行 父组件的 mounted
- 如果业务是父组件引入子组件,并且优先加载子组件的数据,那么请求放在父组件的mounted,如果优先加载父组件的数据,请求放在父组件的created
- 如果没有组件间的依赖关系,那么放在created和mounted 都可以
created如何获取DOM
- 在异步操作里面获取DOM:setTimeout、Promise等
- 使用Vue内置的this.$nextTick
vue获取数据在哪个周期函数?
- 在 created / beforeMounted / Mounted 都可以 如果要操作DOM 在Mounted 操作
vue 中什么是虚拟DOM
- 通过JS创建一个Object 对象来模拟真实DOM结构,这个对象包含标签名(tag)、属性(attrs)和子元素对象(children)三个对象,通过vue中render()函数把虚拟DOM编译成真实DOM,再通过appendChild()添加到页面中
- 创建虚拟DOM就是为了更好将虚拟节点渲染到页面视图中,所以虚拟DOM的节点与真实DOM的属性一一对应;
- 提高性能和减少真实DOM操作次数,从而改善用户渲染节目速度和响应性
vue v-for的key的作用
- key代表的是唯一
- 更高效的更新虚拟dom,提高性能
关于深拷贝和浅拷贝
- 深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用;
- 浅拷贝:只是增加了一个指针指向已存在的内存地址,仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变;
- 深拷贝:增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存;
- 基本数据类型:number、string、boolean、undefined、symbol、BigInt
手写实现浅拷贝
function copy(obj){
const newObj = {}
for(let key in obj){
newObj[key] = obj[key]
}
return newObj
}
实现深拷贝
- lodash的cloneDeep()
- JSON.parse(JSON,stringify(obj)) 这个方法的缺陷:对于部分数据类型,拷贝之后数据会丢失。
- structuredClone() 是专门做深拷贝的API 他有局限 如Error和DOM对象是拷贝不了的