一、为什么data是一个函数?
Vue中data是一个函数的话,这样每复用一次组件,就会返回一份新的data。
组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的。data复用时组件的data数据不受影响。
二、vue中created与mounted的区别
created是在实例创建完成后被立即调用,mounted是模板渲染完成以后被调用。
三、v-model的原理?
v-model原理 :是基于@input/change和v-bind:value封装的语法糖。
四、VUE双向绑定/响应式原理?
通过触发事件打印vue模型数据,发现每个模型数据都有getter、setter方法,代表使用了Object.defineProperty进行数据劫持
五、vue传值有哪些?
1.父级向子集传值:props
2.子集向父级传值:this.$emit
3.公共传值:eventbus或者vuex
六、Vuex有哪几种属性?
有五种,分别是 State、 Getter、Mutation 、Action、 Module。
1.state就是数据源存放地,存放的数据是响应式的。
2.getters 可以对State进行计算操作,getters 可以在多组件之间复用。
3.Mutation来修改数据。
4.Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。
5.Module 可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
七、使用Vuex的好处
1.多层嵌套的组件、兄弟组件间的状态会更好管理维护。
2.缓存一些当前要使用请求远程或本地的数据集(刷新后会自己销毁)。
3.有了第二条,就可以减少向服务器的请求,节省资源。如果你的用户足够多,那么每多出一个请求,对公司来说,都是一大笔钱。
4.对开发者来说,如果你的项目足够复杂,团队的规模也不仅是一个人,数据集中处理更利于程序的稳定和维护。
八、路由传参的几种方式?
方式一:params传参(显示参数)
方式二:params传参(不显示参数)
方式三:query传参
九、params和query的区别?
1.引入方式不同: query要使用path来引入,params要使用name来引入。
2.形成的路径不同(或者url地址显示不同):
① params传递后形成的路径:/router/123,/router/zhangsan
② query传递后形成的路径:/router?id=666&name=zhangsan
3.使用query传参的话,会在浏览器的url栏看到传的参数类似于get请求,使用params传参的话则不会,类似于post请求。
4.是否受动态路径参数影响:Query传递的参数不会受路径参数的影响,会全部展示到路径上,刷新不会丢失query里面的数据;params传递的参数会受路径参数的影响,只会展示含有动态路径参数的部分,刷新会丢失没有设置动态路径参数的params的数据。
十、vue常见的性能优化有哪些?
1.vue 在 v-for 时给每项元素绑定事件需要用事件代理,节约性能。
2.key 保证唯一性,不要使用索引。
3.不要将所有的数据都放在data中。
4.合理使用路由懒加载、异步组件。
5.数据持久化的问题,使用防抖、节流进行优化,尽可能的少执行和不执行。
6.提取公共代码,提取组件的 CSS样式。
7.首页白屏-loading。
8.合理使用 v-if 当值为false时内部指令不会执行,具有阻断功能。
9.第三方插件的按需引入。
十一、v-if和v-for的优先级
v-for比v-if优先级高,一起使用会浪费性能,不建议同时使用,如果必要的情况下,可以选择使用computed过滤掉不需要显示的项目。
十二、异步加载组价
在components中引入组件:
components: {
AsyncComponent: () => import(‘@/components/asyncComponent.vue’)
}
十三、computed计算属性和watch区别以及各自的使用?
computed和watch都是vue框架中的用于监听数据变化的属性。
computed计算属性:使用方法和data中的数据一样,但是类似一个执行方法,在调用时候不加(),必须有return返回,如果函数所依赖的属性没有发生变化,从缓存中读取。
watch监听:函数名称必须和data中的数据名一致,函数有两个参数,前者是newVal,后者是oldVal,函数是不需要调用的,只会监听数据的值是否发生改变,而不会去监听数据的地址是否发生改变,要深度监听需要配合deep:true属性使用,immediate:true 页面首次加载的时候做一次监听。
区别
1、功能:computed是计算属性;watch是监听一个值的变化执行对应的回调
2、是否调用缓存:computed函数所依赖的属性不变的时候会调用缓存;watch每次监听的值发生变化时候都会调用回调
3、是否调用return:computed必须有;watch可以没有
4、使用场景:computed当一个属性受多个属性影响的时候;例如购物车商品结算;watch当一条数据影响多条数据的时候,例如搜索框
5、是否支持异步:computed函数不能有异步;watch可以
十四、vue-router 有哪几种导航钩子?
1.全局导航钩子:router.beforeEach(to,from,next)作用:跳转前进行判断拦截、组件内的钩子、单独路由独享组件
2.路由独享钩子可以在路由配置上直接定义 beforeEnter
3.组件内的导航钩子有三种:
1)beforeRouteEnter 在进入当前组件对应的路由前调用
2)beforeRouteUpdate 在当前路由改变,但是该组件被复用时调用
3)beforeRouteLeave 在离开当前组件对应的路由前调用=
十五、Vue登录实现过程?
在登录的的form表单里面加验证,验证登录名、密码、验证码不能为空,输入验证码时,请求后台接口,验证验证码是否正确,防止暴力登录,点击登录时,将获取的密码进行工要加密(Encrypt.setMaxDigits),将加密后密码、用户名传给后台,登录成功后,跳转到首页(this.$router.push)并返回token和用户信息通过vuex存到缓存中(cookie、localStorage、sessionStorage)。
十六、element可以修改主题颜色吗?
可以,在官网主题里面可以修改,下载theme样式文件,
十七、element的二次开发有哪些?
1.element样式的二次开发例如:el-dialog。
2.两个element组件搭配使用。
3.Element在vue组件中的开发,声明组件名称,在main.js中全局引用,在父级中引用组件,组件作为子集向父级传输请求结果。
十八、slot插槽有几种方式?
1.默认插槽、具名插槽、作用域插槽。
十九、vue同步请求
只要见到返回promise对象,且没有await的,都是异步的,有await的,await一定在async修饰的function中使用,目的是为了达到同步。
二十、await 和 async 的用法
1.async function是声明这个函数是异步函数,function是声明这个函数是同步函数。async函数都会返回一个Promise。
2.await只能放在async函数里。
3.await后边要接一个会return new promise的函数。
4.由此可见,async和await都是promise的语法糖。
二十一、跨域请求
1…利用jQuery的jsonp进行跨域。
2.webpack中的proxy(代理)解决前端跨域。
二十二、一个完整的HTTP请求到底做了什么?
浏览器发起请求-> 解析域名得到ip->浏览器DNS缓存(从操作系统的hosts文件里找、名服务器查找) ->通过IP地址解析协议,找到服务器->建立连接(TCP的三次握手)->发起http请求-> 响应http请求->解析response-> 浏览器渲染展示页面-> 断开连接(TCP的四次挥手)
TCP/IP 协议族按层次分别分为以下 4 层:应用层、传输层、网络层和数据链路层。
二十三、在webpack中配置jquery插件(vue.config.js文件)
form表单验证需要引入rules,在rules里面对字段进行验证,特殊验证可以用:validator
二十四、柱状图、折线图、饼图切换的原理?
在toolbox里面添加onclick时间调用函数事件。
二十五、Js面试题:
1.利用ES6 Set去重
2.利用for嵌套for,然后splice去重(ES5中最常用)
3.利用indexOf去重
4.利用filter的indexOf去重
二十六、Js中new操作的过程
1.帮我们创建了一个空对象
2.将空对象原型的内存地址指向函数的原型对象
3.利用函数的call方法,将原本指向window的绑定对象this指向了obj。
4.利用函数返回对象obj
二十七、undefined和null区别以及作用有哪些?
1.数据类型不同
JavaScript(ECMAScript标准)里共有5种基本类型:Undefined, Null, Boolean, Number,String,可以看到null和undefined分属不同的类型,未初始化定义的值用typeof检测出来是"undefined"(字符串),而null值用typeof检测出来是"object"(字符串)。
2.代表意义不同
undefined是一个特殊值,表示变量已声明但未初始化时的值。
null是一个对象,一个准备用来保存对象,还没有真正保存对象的值。从逻辑角度看,null值表示一个空对象指针,即表示一个对象被定义了,但是值为“空值”。
3.转为数字结果不同
null是一个表示“无”的对象,转为数值时为O;
undefined是一个表示“无”的原始值,转为数值为NaN。
4.undefind和null使用场景不同
undefined表示“缺少值”,即此处应该有一个值,但是还没有定义,典型用法是如下。
(1)如果变量声明了,但没有赋值,它就等于undefined 。
(2)当调用函数时,如果没有提供应该提供的参数,该参数就等于undefined 。
(3)如果对象没有赋值,该属性的值为undefined。
(4)当函数没有返回值时,默认返回undefined。
null表示“ 没有对象”,即此处不应该有值,典型用法是如下。
(1)作为函数的参数,表示该函数的参数不是对象。
(2)作为对象原型链的终点。
二十八、js如何分辨的数据类型?
typeof 能够判断基本数据类型,但是除了null,typeof null 返回的是object但是对于对象来说typeof不能准确判断类型,typeof 函数会返回function,除此之外全部都是object,不能准确判断类型
二十九、数组排序方法:
冒泡排序、选择排序、快速排序
经常用的是js中的sort方法,sort调用一个函数就可以。
三十、es6常用的方法:
箭头函数、import、const、foreach、map、filter、运算符[…]、Promise、async、await。
三十一、map与forEach的区别
forEach 方法,是最基本的方法,就是遍历与循环,默认有 3 个传参:分别是遍历的数组内
容 item、数组索引 index、和当前遍历数组 Array
map 方法,基本用法与 forEach 一致,但是不同的,它会返回一个新的数组,所以 callback
需要有 return 值,如果没有,会返回 undefined
三十二、let和const 的区别是什么?
1.let声明的变量可以改变,值和类型都可以改变;const声明的常量不可以改变。
2.对于复合类型的变量,如数组和对象,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。
3.如果想让定义的对象或数组的内部数据也不能够修改和改变,可以使用object.freeze(names)进行冻结,这样为对象添加新属性就不起作用。除了将对象本身冻结,对象的属性也应该冻结。
三十三、箭头函数和普通函数的区别
1.外形不同:箭头函数使用箭头定义,普通函数中没有。
2.箭头函数都是匿名函数。
3.箭头函数不能用于构造函数,不能使用new。
4.箭头函数中this的指向不同,箭头函数本身没有this,但是它在声明时可以捕获其所在上下文的this供自己使用。
5.箭头函数不绑定arguments,取而代之用rest参数…解决。
6.箭头函数不具有new.target
三十四、实现继承的几种方式
1.父类的实例作为子类的原型(原型链继承)。
2.复制父类的实例属性给子类(构造函数继承)。
3.为父类实例添加新特性,作为子类实例返回(实例继承)。
4.在子类构造函数中拷贝父类实例的所有方法(拷贝继承)。
5.结合了原型链和构造函数继承,通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用(组合继承(1+2 推荐))。
6.通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点(寄生组合继承)。
三十五、JS对象的浅拷贝与深拷贝?
1.浅拷贝(object.assign、扩展运算符方式、concat 拷贝数组、slice 拷贝数组)
1)自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。
2)使用 object.assign 方法有几点需要注意:
① 它不会拷贝对象的继承属性;
② 它不会拷贝对象的不可枚举的属性;
③ 可以拷贝 Symbol 类型的属性。
2.深拷贝(JSON.stringify)
1)深拷贝后的对象与原始对象是相互独立、不受影响的,彻底实现了内存上的分离。
三十六、运算符[…]的作用?
扩展运算符可以去除参数对象中的所有可遍历属性,拷贝到当前对象中。
扩展运算符可以将数组转化为参数序列、复制数组、将字符串转为真正的数组。
三十七、前端的几种存储方式?
前端常用的四种存储方式有cookie、localStorage、sessionStorage、indexedDB。
容量 生命周期 通信
cookie 4kb 可以设置 每次发送请求都会携带在header中
localStorage 5M 永久(需要手动清除) 不参与
sessionStorage 5M 仅在当前对话保留 不参与
indexedDB 不限 永久(需要手动清除) 不参与
1、cookie
主要用于三个方面:
• 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
• 个性化设置(如用户自定义设置、主题等)
• 浏览器行为跟踪(如跟踪分析用户行为等)
优点:兼容性好,请求头携带cookie很方便;缺点:容量小,上限只有4kb,每次请求都自动携带会消耗性能,会被利用与CSRF(跨站请求伪造)攻击;cookie的原生api需要拼接字符串,为了方便一般会再进行封装。
2、localStorage
HTML5加⼊的以键值对(Key-Value)为标准的存储⽅式,优点是操作⽅便,永久性储存(除⾮⼿动删除),⼤⼩为5M。
localStorage 中的键值对总是以字符串的形式存储,对于对象、整数 key 值会自动转换成字符串形式。
3、sessionStorage
与localStorage基本类似,区别是sessionStorage当⻚⾯关闭后会被清理,⽽且与cookie、localStorage不同,他不能在所有同源窗⼝中共享,是会话级别的储存⽅式,会话结束时会被清除
4、IndexedDB
是非关系型数据库,基于文件存储,理论上容量无上限(基于硬盘容量);⽤键值对进⾏储存,可以进⾏快速读取操作;所有操作都要在回调中进行
css
less的深度选择器是/deep/
小程序
1.小程序中如何进行接口请求?会不会跨域,为什么
微信小程序有自带的api接口,wx.request();
不会跨域,因为微信小程序不是浏览器,没有同源策略的约束;
2.微信小程序中的数据渲染与浏览器中有什么不同
浏览器中渲染是单线程的;
而在小程序中的运行环境分成渲染层和逻辑层, WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
3.小程序生命周期
onLoad : 页面加载时触发。一个页面只会调用一次,可以在 onLoad的参数中获取打开当前页面路径中的参数
onShow : 页面显示 / 切入前台时触发调用。
onReady : 页面初次渲染完成时触发,一个页面只会调用一次。
onHide : 页面隐藏 / 切入后台时触发,如 navigateTo 或底部 tab切换到其他页面,小程序切入后台等
onUnload : 页面卸载时触发。如 redirectTo或 navigateBack 到其他页面时.
4.小程序有哪些传递数据的方法
1)使用全局变量
在 app.js 中的 this.globalData = { } 中放入要存储的数据。
在 组件.js 中, 头部 引入 const app = getApp(); 获取到全局变量
直接使用 app.globalData.key 来进行赋值和获取值。
2)使用路由
wx.navigateTo 和 wx.redirectTo 时,可以通过在 url 后 拼接 + 变量, 然后在 目标页面 通过在 onLoad 周期中,通过参数来获取传递过来的值。
3) 使用本地缓存
5.app.json 全局配置文件描述
pages : 用于存放当前小程序的所有页面路径
window : 小程序所有页面的顶部背景颜色,文字颜色配置。
tabBar : 小程序底部的 Tab ,最多5个,最少2个。
echarts图表宽度设置100%,结果echarts宽度只有100px,解决图表自适应宽度问题?
原因
图表的父容器 li 是隐藏的,我默认设置 display:none,图表在执行js初始化的时候找不到这个元素,所以自动将“100%”转成了“100”,最后计算出来的图表就成了100px
解决方法有两种(一种是切换tab以后,li显示以后再初始化图表,二是给li中渲染图表的div提前设置好width 宽度)
第一种可以把图表的实例化写到tab的点击事件中 li 显示之后。
第二种可以给 li 中的 渲染图表的div 提前设置好宽度。因为 li 的宽度100%;h-chart的宽度 赋值为 li的父元素的宽度就好了