前端面试题库

前端题库

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对应修改为您自已的域名   

    }

博客内容源自小豆包
更多内容请到小豆包》

扫码访问小豆包

23_34de43370a343405db1b00359bb895cd.png

扫码关注小豆包公众号

小豆包公众号.jpg

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小豆包3D世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值