面试题总结1

180 阅读8分钟

一、CSS相关面试题?

1.1 flex布局---微信小程序[常用flex:水平垂直居中、左右对称]

学习地址:www.runoob.com/w3cnote/fle…

1.2 移动端适配方案

1. viewport适配

  1. 为什么做viewport适配
  2. 手机厂商在生产手机的时候大部分手机默认页面宽度为980px
  3. 手机实际视口宽度都要小于980px,如: iphone6为375px
  4. 开发需求: 需要将980的页面完全显示在手机屏幕上且没有滚动条
  5. 实现:

2 .rem适配

  1. 为什么做rem适配
  2. 机型太多,不同的机型屏幕大小不一样
  3. 需求: 一套设计稿的内容在不同的机型上呈现的效果一致,根据屏幕大小不同的变化,页面中的内容也相应变化
  4. 实现:
function remRefresh() {
let clientWidth = document.documentElement.clientWidth;
 // 将屏幕等分10份
    let rem = clientWidth / 10;
    document.documentElement.style.fontSize = rem + 'px';
    document.body.style.fontSize = '12px';
}
​
window.addEventListener('pageshow', () => {
   remRefresh()
})
// 函数防抖
let timeoutId;
window.addEventListener('resize', () => {
  timeoutId && clearTimeout(timeoutId);
  timeoutId = setTimeout(() =>{
     remRefresh()
  }, 300)
})
​
  1. 第三方库实现

lib-flexible + px2rem-loader

1.3 link与@import区别

blog.csdn.net/weixin_4434…

本质上,这两种方式都是为了加载css文件,但还是存在细微的差别。

  • 差别1:老祖宗的差别,link属于XHTML标签,而@import完全是css提供的一种方式。 link标签除了可以加载css外,还可以做很多其他的事情,比如定义RSS,定义rel连接属性等,@import只能加载CSS。
  • 差别2:加载顺序的差别:当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再加载。所以有时候浏览@import加载CSS的页面 时会没有样式(就是闪烁),网速慢的时候还挺明显。
  • 差别3:兼容性的差别。由于@import是CSS2.1提出的所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题,完全兼容。
  • 差别4:使用dom控制样式时的差别。当使用JavaScript控制dom去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的(不支持)。
  • 差别5(不推荐):@import可以在css中再次引入其他样式表,比如创建一个主样式表,在主样式表中再引入其他的样式表

二、业务面试

2.1 防抖节流面试:基本改变、原理[闭包+延迟器]

相同:在不影响客户体验的前提下,将频繁的回调函数,进行次数缩减.避免大量计算导致的页面卡顿.

不同:防抖是将多次执行变为最后一次执行,节流是将多次执行变为在规定时间内只执行一次.

//防抖函数
    function debounce(func, wait) {
        var timeout;
        return function () {
            var context = this;
            var args = arguments;
            clearTimeout(timeout)
            timeout = setTimeout(function () {
                func.apply(context, args)
            }, wait);
        };
    };
​
//节流函数
function throttle(func, wait){
    var context, args, timeout;
    return function() {
        context = this;
        args = arguments;
        if(!timeout) {
            timeout = setTimeout(function(){
                func.apply(context, args);
                timeout = null;
            }, wait);
        }
    }
}
​

开发的时候防抖与节流功能使用lodash

2.2 路由传递参数?

问题:vue-router路由传递参数有几种形式?

答:params|query

问题:如何通过代码获取query|params参数?

答:this.route.params.xxxthis.route.params.xxx this.route.query.xxxx

问题:params参数可有可无?

答:在路由配置文件中,在占位符后面加一个问号

问题:routerrouter与route区别?

答:router:路由器,用来管理路由,实现编程式导航router:路由器,用来管理路由,实现编程式导航 route:路由,可以获取路由相关的参数:path、query、params、meta等等

路由传递参数:传递基本类型数据没有问题,但是不能传递引用类型数据

2.3 组件通信手段有哪些?

props 自定义事件 全局事件总线 vuex v-model ref attrsattrs lisenters parentparent children sync 插槽

2.4 图片懒加载实现原理是啥?

blog.csdn.net/weixin_4402…

2.5 工作的时候,是否自己封装过通过的组件?

我的工作时候自己封装过一些通用的组件:分页器(实现的)、按钮等等

2.6 项目优化手段有哪些?

防抖与节流 路由懒加载 事件委派 按需引入 v-if|v-show ***** 请求次数的优化->三级分类发请求App.vue

2.7 项目持久化你们用什么?有什么缺点?

locaStore|sessionStroage:存储数据上限5M

2.8 vuex相关?

vuex核心概念有哪些, state mutations actions getters modules

v-model能否直接修改vuex仓库数据:不能走流程

vuex是不是持久存储数据

2.9 购物车如何实现?说说原理?

通过请求头携带功能参数:token|userTempId,服务器会通过标识的表示返回相应的数据!!!!

2.10 Promise相关面试?

手写Promise

//声明函数        执行器   『同步回调』
​
function Promise(executor) {
    //设置实例对象的属性
    this.PromiseState = 'pending';
    this.PromiseResult = undefined;
    this.callbacks = [];
​
    //声明函数
    const success = (value) => {
        if (this.PromiseState !== 'pending') return;
        //修改状态为成功  PromiseState
        this.PromiseState = 'fulfilled';
        //设置成功的结果值 PromiseResult
        this.PromiseResult = value;
        //调用回调
        if (this.callbacks.length > 0) {
            this.callbacks.forEach(cbObj => {
                //执行成功的回调
                cbObj.ok();
            })
        }
    }
​
    const fail = (reason) => {
        if (this.PromiseState !== 'pending') return;
        //修改状态为失败  PromiseState
        this.PromiseState = 'rejected';
        //设置成功的结果值 PromiseResult
        this.PromiseResult = reason;
        //调用回调
        if (this.callbacks.length > 0) {
            this.callbacks.forEach(cbObj => {
                //执行成功的回调
                cbObj.ng();
            })
        }
    }
​
    try {
        //调用执行器函数
        executor(success, fail);
    } catch (e) {
        //调用 fail 函数
        fail(e);
    }
}
​
Promise.prototype.then = function (onFulfilled, onRejected) {
​
    //判断  异常穿透
    if(typeof onRejected !== 'function'){
        onRejected = reason => {throw reason};
    }
​
    //值传递
    if(typeof onFulfilled !== 'function'){
        onFulfilled = value => value;
    }
​
    return new Promise((resolve, reject) => {
        //封装函数简化代码
        let callback = (type) => {
            try {
                let res = type(this.PromiseResult);
                //判断
                if (res instanceof Promise) {
                    res.then(v => {
                        resolve(v);
                    }, r => {
                        reject(r);
                    })
                } else {
                    resolve(res);
                }
            } catch (e) {
                reject(e);
            }
        }
​
        //判断 成功
        if (this.PromiseState === 'fulfilled') {
            setTimeout(() => {
                callback(onFulfilled);// 
            })
        }
​
        //失败
        if (this.PromiseState === 'rejected') {
            setTimeout(() => {
                callback(onRejected);
            })
        }
​
        //pending 
        if (this.PromiseState === 'pending') {
            //保存回调
            this.callbacks.push({
                ok: function () {
                    //成功
                    callback(onFulfilled);
                },
                ng: function () {
                    callback(onRejected);
                }
            })
​
        }
​
    });
}
​
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}
​
Promise.resolve = function(value){
    return new Promise((resolve,reject) => {
        //判断
        if(value instanceof Promise){
            //value.then(resolve, reject); 这行代码和下面5行代码功能一样
            value.then(v=>{
                resolve(v);
            }, r => {
                reject(r);
            });
        }else{
            resolve(value);
        }
    })
}
​
Promise.reject = function(reason){
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}
​
​
Promise.all = function (promiseArr) {
    return new Promise((resolve, reject) => {
        let count = 0;
        let arr = [];
        for (let i = 0; i < promiseArr.length; i++) {
            promiseArr[i].then(v => {
                count++;
                arr[i] = v;
                if (count === promiseArr.length) {
                    resolve(arr);
                }
            }, r => {
                reject(r);
            });
        }
    });
}
​
​
Promise.race = function (promiseArr) {
    return new Promise((resolve, reject) => {
        promiseArr.forEach(item => {
            item.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            });
        });
    });
}
​

2.11 token相关面试?

token:token是令牌,是用户唯一身份标识,当用户登录成功以后获取相应的token!!

token用途:可以利用token获取用户信息!!!

token过期怎么处理:清空本地数据、发请求通知服务器清空数据、让用户重新登录获取新的token!!!

2.12 守卫?

守卫有几种:三种 全局守卫:beforeEach、afterEach 路由独享守卫:beforeEnter 组件内守卫:beforeRouteEnter beforeRouteUpdate (2.2 新增) beforeRouteLeave

2.13 axios自己是否封装过?封装作用是什么?

答:axios我曾经自己封装过,主要为了添加请求、响应拦截器!!!

请求响应拦截器有啥功能:进度条、请求拦截器携带公共参数!!!

2.14 数组去重|深拷贝|浅拷贝|

数组去重:indexOf

​
递归实现深拷贝
//老对象
   let obj = {
        name : 'atguigu',
        pos : ['北京','上海','深圳','武汉','西安'],
        founder : {
            name : '刚哥',
            age : 35
        },
        test:function(){
            console.log('测试')
            console.log(this)
        }
    }
​
    //封装深拷贝函数
    function deepClone(oldObj){
        //1.准备一个容器(对象 数组)
        let wrapper;
        //2.根据老对象判断数据类型,决定容器是 {} 还是 []
        let type = getDataType(oldObj)
        if(type === 'Array'){
            wrapper = [];
        }
        if(type === 'Object'){
            wrapper = {}
        }
        //3.给容器添加新属性
        //枚举老对象的属性
        for(let item in oldObj){
            //item 是对象的每一个属性
            // wrapper[item] = '123'
            //根据属性值的数据类型去添加
            let typeItem = getDataType(oldObj[item])
           
            if(typeItem === 'Object' || typeItem === 'Array'){
                //如果是对象或者数组,
                wrapper[item] = deepClone(oldObj[item]);
                
            }else if(typeItem === 'Function'){
                //如果是函数,通过 bind()去添加
                wrapper[item] = oldObj[item].bind(wrapper)
            }else{
                //如果是普通的数据类型,直接添加
                wrapper[item] = oldObj[item];
            }
​
        }
​
        //返回值:是新对象
        return wrapper;
    }
​
   //新对象
   let newObj = deepClone(obj)
   console.log(newObj)
​
​
​
    //封装函数:判断数据类型的
    function getDataType(data) {
        if(typeof data === 'object'){
            if(data instanceof Array){
                //数组
                return 'Array';
            }else {
                //对象
                return 'Object';
            }
        }else if(typeof data === 'function'){
            //函数
            return 'Function';
        }else {
            //num str bool (基本数据类型)
            return false;
        }
    }

2.15 跨域

JSONP,百度预搜索 CROS 代理跨域

2.16 后台项目一般架子用的是element-UI!!!![element-ui版本问题:不同版本写法不一样]

form、button、table、pagination、card等等

2.17 scoped作用?底层原理是啥那?

scoped作用:局部样式[子组件只有根节点可能受到影响] 当前VC加上scoped属性后:DOM节点和子组件根节点,添加上相同的data-v-xxxx,通过属性选择器实现的!!!

2.19 功能时候用element-ui插件如何调试样式?深度选择器

>>>     /deep/   ::v-deep  

2.20 菜单|按钮权限原理你说说? ******

第一步:将项目的路由进行拆分:常量路由、异步路由、任意路由

第二步:根据用户的信息筛选出用户全部路由!!!

2.21 你用过echarts吗?echarts是啥?

数据可视化的插件,底层用什么写的

2.22 HTML5中新增了特性?

语义化标签:nav、footer、main、canvas CSS3 动画、2D、3D 多媒体:视频、音频 本地存储 canvas

2.23 ES6新增那些特性?

let const 箭头函数、数组迭代方法、set、map 、symbol等等

2.24 数组的迭代方法你知道那些>

forEach\filter\map\reduce

2.25 reduce引用的场景!!! 购物车计算综合

2.26 闭包的应用场景?

闭包面试:可以访问外层作用于变量的函数,称之为闭包。 闭包的缺点,对于外部引用一致存在,耗内存!!! 防抖与节流

2.27 nextTicknextTick与set