前端面试题浅答

1.vue双向绑定的原理是什么?里面的关键点在哪里?

vue2的双向绑定时通过object.defineProperty()去劫持各个属性的setter,getter,在数据变动时,发布消息给订阅者,触发相应的监听回调来渲染视图。

直接定义一个新属性,或者修改一个现有属性,并返回此对象

缺点:检测不到对象属性的添加和删除

数组API方法无法监听到 数组的api方法在vue2里面进行了重写

需要对每个属性进行遍历监听,如果嵌套对象,需要深层监听,造成性能问题

vue3 es6新增的Proxy的监听是针对一个对象的,那么对这个对象的所有操作都会进入监听操作,就可以实现代理所有属性 通过new Proxy 并传入对应的操作函数实现

object.definePropetry劫持对象的属性

proxy 劫持整个对象

2.实现水平垂直居中的方式

父盒子display:flex;algin-item:center;justify-conent:center;

如果知道子盒子的高度 margin:calc((100% - xxx) / 2) auto;

3.常用的伪元素有哪一些

:before :after  :hover  :nth-child(1) :last-child :first-child :actived  :visted

4.移动端如何适配不同屏幕尺寸

用rem 作为单位 原理 根元素设置字体大小 别的单位用rem

用百分比进行布局

用view-port结合媒体查询进行布局

5.本地存储有哪一些?他们三者有什么区别

cookie 客户端本地存储  session 服务器存储     localstorge 持久化本地存储 sessionstorge 会话存储

7.js的数据类型有哪些?如何判断js的数据类型

字符串string 数字 number 布尔boolean null空 undefined未定义 对象object(function函数 array数组 object对象) symbol唯一标识

typeof 返回的是字符串 支持检查的 布尔不支持 支持6种

instanceof  后面跟大写 返回布尔值  

8.let const var三者有什么区别

let 不会有变量提升 使用必须在声明之后 同一作用域不允许重复使用

const 常量 定义之后不能更改 但是如果是对象的内部是可以更改的

var 定义一个变量 会有变量提升 提升到顶部

9.数组去重有哪些办法

排序 重复就删除

定义一个对象 一个新数组 去重

[...new Set(xxx)] 去重

10.说一下深拷贝和浅拷贝 ,如何自己实现一个浅拷贝

浅拷贝:只复制指向对象的指针,而不复制对象本身,新旧对象共享一块内存

深拷贝:复制并创建一个一模一样的对象,不能共享内存,修改新对象,旧对象保存不变

object.assgin(目标对象,原对象) 只有一层是深拷贝 多层是浅拷贝

[...xxx] 深拷贝

11.vue的生命周期有哪一些,说一下它们每个阶段都做什么作用

vue2

创建 渲染 更新 销毁

beforeCreated  

created 最早可以操控到数据的地方

beforemounted  

mounterd 发请求执行方法

beforeupdate 更新之前

updated 更新后

beforedestory 销毁前 在这做解绑事件

destory 销毁后

vue3

beforecreated 和created 用 setup 替代

别的前缀换成 on 和onun  写箭头函数

12.组件通讯的方式

vue2

父向子props 父组件通过:xxx='xxx'传入数据  子组件用props接收

子向父 $emit 父组件@xxxx 子组件 this.$emit(xxxx,参数) 触发

ref  打上这个标签以后 父组件可以直接通过这个调用子组件的方法和更改数据

事件总线 $emit,$on,$off 分别为分发、监听、取消监听事件 eventBus

localStorage/sessinStorage 存储

vueX

vue3

vue3 从 实例中 移除了 $on $off $once 方法,所以我们如果想要继续使用全局事件总线,要通过第三方库

mitt

pinia

vueX

13.vueX有几个属性及作用

actions 发请求的地方

mustationa 更改数据的地方

state  存储数据的地方

getter  处理数据的地方

modules 模块化vueX

14.vue的监听属性和计算属性又什么区别

计算属性依赖数据变才会触发操作

监听属性 数据变就会触发操作 监听属性 和处理函数 要不要开启深度监听

15.说一下防抖和节流,怎么实现

防抖 n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

节流 n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

function throttled(fn, delay) {

    let timer = null

    let starttime = Date.now()

    return function () {

        let curTime = Date.now() // 当前时间

        let remaining = delay - (curTime - starttime)  // 从上一次到现在,还剩下多少多余时间

        let context = this

        let args = arguments

        clearTimeout(timer)

        if (remaining <= 0) {

            fn.apply(context, args)

            starttime = Date.now()

        } else {

            timer = setTimeout(fn, remaining);

        }

    }

}
function debounce(func, wait, immediate) {

    let timeout;

    return function () {

        let context = this;

        let args = arguments;



        if (timeout) clearTimeout(timeout); // timeout 不为null

        if (immediate) {

            let callNow = !timeout; // 第一次会立即执行,以后只有事件执行后才会再次触发

            timeout = setTimeout(function () {

                timeout = null;

            }, wait)

            if (callNow) {

                func.apply(context, args)

            }

        }

        else {

            timeout = setTimeout(function () {

                func.apply(context, args)

            }, wait);

        }

    }

}

16.vue的导航守卫有哪些

全局守卫 组件内的守卫  路由独享守卫

17.你的登录拦截是怎么实现的

http拦截 判断本地是否存在token

路由拦截

18.你用有个图表库吗?用的是什么

echrats

19.闭包是什么

内部对外部的引用造成的内存泄露 导致不能被垃圾处理机制回收掉

20.vue2和vue3的区别

21.vue的常用指令有哪些

v-if v-for v-bind : v-model  v-on  v-text v-html v-once

22.v-if 和v-show有什么区别

v-show dispaly:none 控制显示和隐藏

v-if 添加移除dom

v-show性能更佳 但是一般都用v-if

23.v-for为什么要加一个key

唯一标识

vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM

24.你是如何封装一个组件的

根据需求 考虑这个组件的功能然后封装组件 一般都是对element的组件根据需求进行二次的封装

25.有个自己从0到1搭建项目吗

26.有用过uniapp吗

27.你会写后台吗?搞过服务端渲染吗

28.说一下你在项目中遇到的难点,如何解决的

29.url到浏览器的一个过程有哪些步骤

你输入挨个请求资源 请求到的渲染 请求不到的报错

浏览器根据请求的 URL 交给 DNS 域名解析,找到真实 IP ,向服务器发起请求;

服务器交给后台处理完成后返回数据,浏览器接收⽂件( HTML、JS、CSS 、图象等);

浏览器对加载到的资源( HTML、JS、CSS 等)进⾏语法解析,建立相应的内部数据结构 (如 HTML 的 DOM);

载⼊解析到的资源⽂件,渲染页面,完成。

30.如何实现小程序的的request拦截及封装

import {

  baseUrl

} from "./base.js";

import store from '@/store/index.js';



// console.log('请求封装')



const get = function(url) {

  return function(params) {

    return new Promise((resolve, reject) => {

      // console.log(store.state.moduleUser)

      uni.request({

        url: baseUrl + url,

        responseType: url == '/api/weixin/getWxacodeunlimit' ? 'arraybuffer' : 'text',

        method: 'get',

        header: {

          Authorization: store.state.moduleUser.token

        },

        data: params,

        success: res => {

          // console.log('*********GET-orderp请求: ', res)

          try {

            if (res.data.code === 200) {

              resolve(res.data.data)

            } else if (!res.data.code) {

              resolve(res.data)

            } else {

              reject(res.data)

            }

          } catch (e) {

            //TODO handle the exception

            reject(e)

          }

        },

        fail: err => {

          // console.log('*********GET错误', err)

          reject(err)

        }

      })

    })

  }

};



const post = function(url) {

  return function(params) {

    return new Promise((resolve, reject) => {

      uni.request({

        url: baseUrl + url,

        method: 'post',

        header: {

          Authorization: store.state.moduleUser.token

        },

        data: params,

        success: res => {

          // console.log('*********POST-orderp请求: ', res)

          try {

            if (res.data.code === 200) {

              resolve(res.data.data || res.data.success)

            } else {

              reject(res.data)

            }

          } catch (e) {

            //TODO handle the exception

            reject(e)

          }

        },

        fail: err => {

          console.log(err)

          reject(err)

        }

      })

    })

  }

};



export {

  get,

  post

}

31.在import {

  baseUrl

} from "./base.js";

import store from '@/store/index.js';



// console.log('请求封装')



const get = function(url) {

  return function(params) {

    return new Promise((resolve, reject) => {

      // console.log(store.state.moduleUser)

      uni.request({

        url: baseUrl + url,

        responseType: url == '/api/weixin/getWxacodeunlimit' ? 'arraybuffer' : 'text',

        method: 'get',

        header: {

          Authorization: store.state.moduleUser.token

        },

        data: params,

        success: res => {

          // console.log('*********GET-orderp请求: ', res)

          try {

            if (res.data.code === 200) {

              resolve(res.data.data)

            } else if (!res.data.code) {

              resolve(res.data)

            } else {

              reject(res.data)

            }

          } catch (e) {

            //TODO handle the exception

            reject(e)

          }

        },

        fail: err => {

          // console.log('*********GET错误', err)

          reject(err)

        }

      })

    })

  }

};



const post = function(url) {

  return function(params) {

    return new Promise((resolve, reject) => {

      uni.request({

        url: baseUrl + url,

        method: 'post',

        header: {

          Authorization: store.state.moduleUser.token

        },

        data: params,

        success: res => {

          // console.log('*********POST-orderp请求: ', res)

          try {

            if (res.data.code === 200) {

              resolve(res.data.data || res.data.success)

            } else {

              reject(res.data)

            }

          } catch (e) {

            //TODO handle the exception

            reject(e)

          }

        },

        fail: err => {

          console.log(err)

          reject(err)

        }

      })

    })

  }

};



export {

  get,

  post

}

31.在vue项目中,不用框架怎么封装

32.什么是js原型,原型链式什么?

每个对象都拥有一个原型对象 propertype

35.作用域是做什么的?

表示一个区间,在这个区间内声明的所有内容(比如方法或变量)都可以被该区间内的代码访问到。

36.操作数组的方法有哪些

slice splice pop push unshift shift indexOf lastindexOf sort resvese foreach filter some every

37.0.1+0.2等于0.3吗

parsetfloat

38.keep-alive是什么?有哪几个什么周期?

组件保活 是一个标签

当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

39.判断一个数据是不是数组

instandeof Array

Array.isArray

40.判断一个变量是否是对象

typeof

41.对象和数组的常用方法与哪些

object.keys() object.values object.entries() object.freeze()

42.创建一个空数组、空对象有哪些方式

字面量 构造函数

43.哪写遍历方式会改变原数组

所有遍历方法都不会影响原数组

44.set 和map分别是什么

es6新增的数据结构

set不允许重复 类似数组

add has

map 键值对的集合 不同于对象只有字符串可以当键 map变量也能当键

set get  has

45.介绍一下promise

期约 即承诺的意思

简单就是一个容器,里面保存这某个未来才会结束的事件(通常就是一个异步操作)的结果。从语法上来说,promise是一个对象,从它可以获取异步操作的消息

46.promise 通常会解决三种问题

回调地狱 用then方法解决

同时发起对公异步请求,谁有结果就先拿谁的 race

发起对公请求,等到所有请求后再做下一步绝对all

47.如何改变一个函数a的上下文

call aply bind

48.call 和aply有什么区别

apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。

call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。

49.eventbus 是个什么东西

事件总线 用来组件之间通信的 如果项目过大 十分不好维护

$emit $on

50.vue中普通的生命周期有哪些

51.父子组件执行的生命周期的顺序是怎么样的

父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted->父beforeUpdate->子beforeUpdate->子updated->父updated->父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

52.minxins有几个生命周期阶段

mixin的生命周期钩子在组件的生命周期钩子之前执行

mixin的beforeCreate > 父beforeCreate > mixin的created > 父created > mixin的beforeMount > 父beforeMount > 子beforeCreate > 子created > 子beforeMount > 子mounted > mixin的mounted >父mounted

53.弹性布局一行两列,一行固定宽,如何实现

父:dispaly:flex

子 width:xxx, 子flex:1

54.flex:1包含哪三种属性

flex-grow:子盒子除了基础宽度外所占父盒子多余空间的比例

flex-basis:子盒子的基础宽度

flex-basis决定了子盒子一开始的宽度,假如width设置了200,flex-basis不设置默认就是auto,最终宽度就会采用width,如果width不设置就是auto,flex-basis设置100,最终宽度就会采用100,如果两者都不设置,就都为auto,那么子盒子的最终宽度就是内容大小来决定,被内容撑开;如果两者都设置,则flex-basis会覆盖width,最终采用flex-basis;

flex-shrink:子盒子除了基础宽度外所占父盒子溢出空间的比例

shrink和grow则相反,假如父盒子500,子盒子的宽度加起来为600,那么就溢出了100,flex-shrink就决定了每个子盒子占100的比例,子盒子的最终宽度就是基础宽度或者width加上溢出这一部分的宽度;

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值