前端题库
vue 题
1. v-once 只渲染元素和组件一次,优化更新渲染性能
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
2. Vue的响应式原理
https://www.cnblogs.com/fundebug/p/responsive-vue.html
数据劫持=> 观察者 =》 发布者 =》 订阅者
在生成vue实例时,为对传入的data进行遍历,使用Object.defineProperty把这些属性转为getter/setter
observer dep watcher
每个vue实例都有一个watcher实例,它会在实例渲染时记录这些属性,并在setter触发时重新渲染
3. keep-alive有哪些参数?
include 值为字符串或者正则表达式匹配的组件name会被缓存
> include 值是组件中的name命名,而不是路由中的组件name命名
exclude 值为字符串或正则表达式匹配的组件name不会被缓存
除了这个我们还可以利用路由中的meta属性来控制
{
path: '/c',
name: 'c',
meta:{
keepAlive:true
},
component: () => import('../views/C.vue')
},
使用方式:
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
这样组件的缓存是实现了,但是还是会有一些问题,就是因为组件被缓存,并没有被销毁,
所以组件在切换的时候也就不会被重新创建,自然也就不会调用created等生命周期函数,
所以此时要结合生命周期activated与deactivated来获取当前组件是否处于活动状态
activated() {
console.log("----------进activated--------");
},
deactivated() {
console.log("----------进deactivated--------");
}
开启了keep-alive后,当再次进入(前进或者后退)时,只触发activated,退出时触发deactivated
4. computed与methods的区别与侦听属性watch的区别?
区别就是computed有缓存,methods没有缓存,每次都重新计算
computed适合监听多个数据变化导致一个结果变化的场景。
watch适合一个数据变化,导致多个结果变化的场景
5. vue中watch 参数
handler (newval , oldval), deep: 监听深度对象属性 , immediate: 初次挂载执行一次handler函数
watch: {
Name: {
handler(newName, oldName) {
// ...
},
deep: true,
immediate: true
}
}
6. vue SPA首屏加载慢如何解决
1. 使用CDN资源 不打包库文件
index.html 引入cdn 库文件
webpack 配置
externals: {
'element-ui': 'ELEMENT',
'vue': 'Vue',
'axios': 'axios',
'echarts': 'echarts',
'vue-router': 'VueRouter'
},
2. Nginx 开启 gzip
》前端将文件打包成.gz文件,然后通过nginx的配置,让浏览器直接解析.gz文件
webpack的配置
productionGzip: true,
productionGzipExtensions: ['js', 'css'],
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
》 Nginx开启gzip,修改nginx配置文件 nginx.conf:
http {
...
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
#gzip_http_version 1.1;
gzip_comp_level 2; # 压缩级别
# 要压缩的mine类型
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss image/jpeg image/gif image/png image/svg+xml;
gzip_vary off;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\."; # IE6不支持gzip
...
}
3. 异步路由加载
// 异步加载方案
const Index = r =>
require.ensure([], () => r(require('@/pages/index')), 'Index')
const ChooseUser = r =>
require.ensure([], () => r(require('@/pages/detail/chooseUser')),'ChooseUser')
Vue.use(Router)
4. 关闭sourcemap
productionSourceMap:false
每个js都带一个sourcemap,有时sourcemap会很大
5. loading效果
》 首页加个好看的loading阻塞一下,让用户别等的那么心烦
6. 首页单独做服务端渲染
> 用node的mvc框架(比如express)做首页渲染,而下面的子页面仍用spa单页(将vue打包的dist目录放在public目录下,当静态资源来访问)
7. 按需加载ui 组件库小组件
》 比如ehcart 固定组件使用,在固定组件里面安装挂载
8. DllPlugin 和 DllReferencePlugin 提升构建速度
9. wabpack-bundle-analyzer 分析工具分析打包后性能
10. 雪碧图合并 阿里icon库合并图标
11. 善用缓存 keep-alive locastorge sessionStoreg cookei indexdb 减少watch 使用 computed
12. v-if or v-show 合理使用 requestAnimationFrame 替代 setinterval
7. vuex 是什么
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex
modules里面如果主动写namespace为true, 会导致modules里面的actions\mutaions\gatters变成局部作用域
8. axios网络慢请求超时处理
1. 判断请求异常信息中是否含有超时timeout字符串 处理请求超时
if (error.message.includes('timeout')) {
// Notice.error({
// title: error.code,
// desc: error.message
// })
} else {
const { request: { statusText, status }, config } = JSON.parse(JSON.stringify(error))
errorInfo = {
statusText,
status,
request: { responseURL: config.url }
}
}
2. 做全局重复请求次数计算 没超过重新执行 axios()抛出pamise 超过 走提示异常
9. nextTick 原理是什么?
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用
先定义了一个callbacks 存放所有的nextTick里的回调函数
然后判断一下当前的浏览器内核是否支持 Promise,如果支持,就用Promise来触发回调函数
如果不支持Promise再看看是否支持MutationObserver,是一个可以监听DOM结构变化的接口,观察文本节点发生变化时,触发执行所有回调函数。
如果以上都不支持就只能用setTimeout来完成异步执行了。
关于nextTick setTimout promse 执行顺序
created () {
setTimeout(() => {console.log('sittimeout')}, 0)
new Promise((reslove, reject) =>{
console.log('promise')
reslove('r')
}).then(() => {
console.log('then')
})
this.$nextTick(() => {
console.log('nexttick')
})
},
打印顺序
1. promise
2. then
3. nexttick
4. setitimeout
created () {
setTimeout(() => {console.log('sittimeout')}, 0)
this.$nextTick(() => {
console.log('nexttick')
})
new Promise((reslove, reject) =>{
console.log('promise')
reslove('r')
}).then(() => {
console.log('then')
})
},
打印顺序
1. promise
2. nexttick
3. then
4. setitimeout
webpack
webpack 如何配置多入口
1. 数组形式:
entry: {
main: [
"./src/main.js",
"./src/pageTwo/index.js"
]
},
2、对象语法:
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
output: {
path: path.reslover(__dirname, 'dist')
filename: `[name].publicjs.js`
}
webpack loader和plugin区别
1. loader
用于对模块源码的转换,loader描述了webpack如何处理非javascript模块,并且在buld中引入这些依赖。loader可以将文件从不同的语言(如TypeScript)转换为JavaScript,或者将内联图像转换为data URL。比如说:CSS-Loader,Style-Loader等
loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中
处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行
第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码
2. plugin 在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果
class MyPlugin{
constructor(options){
console.log("MyPlugin constructor:", options);
}
apply(compiler){
compiler.plugin("compilation", compilation => {
console.log("MyPlugin");
});
}
}
module.exports = MyPlugin;
plugins: [
new MyPlugin({param: "my plugin"})
]
webpack 生命周期是什么?
webpack tree shaking目的是什么?怎么实现的?
概念:1 个模块可能有多个⽅法,只要其中的某个⽅法使⽤到了,则整个⽂件都会被打到 bundle ⾥⾯去,tree shaking 就是只把⽤到的⽅法打⼊ bundle ,没⽤到的⽅法会在 uglify 阶段被擦除掉。
https://juejin.im/post/5a4dca1d518825128654fa78
什么是闭包,闭包为解决什么问题而生的?
闭包就是能够读取其他函数内部变量的函数。在js中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁
特点:
1. 可以避免使用全局变量,防止全局变量污染
2. 隐藏变量
3. 内存泄漏 原因 IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量
4. 函数嵌套函数
5. 函数内部可以引用函数外部的参数和变量
6. 保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
7. 解决如何从外部读取局部变量
proxy 是什么? 原理是什么?
proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截
let proxy = new Proxy(target, handler)
new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为
let target = {
name: 'aaa'
};
let testHandler = {
get: function(target, key) {
console.log(`${key} 被读取`);
return target[key];
},
set: function(target, key, value) {
console.log(`${key} 被设置为 ${value}`);
target[key] = value;
}
}
let targetConsole = new Proxy(target, testHandler);
targetConsole.name; // 控制台输出:name 被读取
targetConsole.name = 'bbb'; // 控制台输出:name 被设置为 bbb
console.log(target.name); // 控制台输出: bbb
移动端1px解决方案
原因: 了解两个概念,一个是像素(pixel)可以简写为px,另外一个是设备像素比(DPR),
不同的手机有不同的像素密度导致的。如果移动显示屏的分辨率始终是普通屏幕的2倍,1px的边框在devicePixelRatio=2的移动显示屏下会显示成2px
解决方案1
<!--全部边框-->
.border-1px:after {
content: '';
position: absolute;
box-sizing: border-box;
top: 0;
left: 0;
width: 200%;
height: 200%;
border: 1px solid #000;
border-radius: 4px;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: top left;
}
<!--单边框,以上边框为例-->
.border-1px-top:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
border-top: 1px solid red;
transform: scaleY(.5);
transform-origin: left top;
}
方案二
增加媒体查询分别对不同 DPR 的设备,进行不同的缩放
.border(
@borderWidth: 1px;
@borderStyle: solid;
@borderColor: @lignt-gray-color;
@borderRadius: 0) {
position: relative;
&:before {
content: '';
position: absolute;
width: 98%;
height: 98%;
top: 0;
left: 0;
transform-origin: left top;
-webkit-transform-origin: left top;
box-sizing: border-box;
pointer-events: none;
}
@media (-webkit-min-device-pixel-ratio: 2) {
&:before {
width: 200%;
height: 200%;
-webkit-transform: scale(.5);
}
}
@media (-webkit-min-device-pixel-ratio: 2.5) {
&:before {
width: 250%;
height: 250%;
-webkit-transform: scale(.4);
}
}
@media (-webkit-min-device-pixel-ratio: 2.75) {
&:before {
width: 275%;
height: 275%;
-webkit-transform: scale(1 / 2.75);
}
}
@media (-webkit-min-device-pixel-ratio: 3) {
&:before {
width: 300%;
height: 300%;
transform: scale(1 / 3);
-webkit-transform: scale(1 / 3);
}
}
.border-radius(@borderRadius);
&:before {
border-width: @borderWidth;
border-style: @borderStyle;
border-color: @borderColor;
}
}
.border-all(
@borderWidth: 1px;
@borderStyle: solid;
@borderColor: @lignt-gray-color;
@borderRadius: 0) {
.border(@borderWidth; @borderStyle; @borderColor; @borderRadius);
}
线程和进程各自有什么区别和优劣呢?
浏览器的重绘与回流?
前端监控是怎么做的?
前端埋点统计怎么做的?
Web-Worker 是什么,解决什么问题的?
https://segmentfault.com/a/1190000023011282?utm_source=tag-newest
JavaScript 事件循环机制是什么?
https://www.cnblogs.com/yqx0605xi/p/9267827.html
原型链的顶层是什么?
原型链的顶层就是Object.prototype,而这个对象的是没有原型对象的。
浏览器输入 Object.__proto__ 执行结果是:
ƒ () { [native code] }
prototype 是函数 Function 才有的属性 , __proto__是所有对象都有的属性
什么是前端serverless?
讲一下强缓存和协商缓存?它们之间的区别是什么?
js 模块化是什么? 做了那些历史演变?
手写一个 Promise。
function Promise(exector) {
let self = this;
//status表示一种状态
let status = "pending";
let value = undefined;
let reason = undefined;
//成功执行
function resolve(value) {
if (status == 'pending') {
self.value = value;
self.status = "resolve";
}
}
//执行失败
function reject(reason) {
if (status == 'pending') {
self.reason = reason;
self.status = "reject"
}
}
//对异常操作
try {
exector(resolve, reject)
} catch (e) {
reject(e)
}
//设置promise的then方法
Promise.prototype.then = function(reject, resolve) {
let self = this;
if (this.status == 'resolve') {
reject(self.value)
}
if (this.status == 'reject') {
resolve(self.reason)
}
}
}
//new 一个promise 进行测试
let promise = new Promise((reject, resolve) => {
resolve("return resolve");
});
promise.then(data => {
console.log(`success${data}`);
}, err => {
console.log(`err${err}`);
})
说一下js的垃圾回收机制,是什么阶段进行垃圾回收?
OSI 七层模型和TCP/IP模型及对应协议 ?
如何防止cookie 伪造
解决方案:
在cookie的domin加上自己的token做token校验
如何防止攻击者获取token,进行接口的脚本提交攻击
解决方案: 在接口的统一封装入口,做哈希令牌,访问进行接口的令牌校验
vue 在nginx下页面刷新出现404问题
location /xx/xx/ {
root /;
index index.html;
try_files $uri $uri/ /xx/xx/index.html
}
如何把http转向https
1. 可以在服务器端设置301重定向,让http自动跳转到https
res.writeHead(301,{
'Location':'https://...'
});
res.end();
2. 80 重定向
server
{
listen 80;
server_name abc.com;
rewrite ^(.*) https://www.abc.com$1 permanent; # abc.com对应修改为您自已的域名
}
扫码访问小豆包