VUE
-
Vue 组件中 data 为什么必须是函数
因为一个组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象。 -
说一下v-if和v-show的区别
v-if和v-show都可以显示和隐藏一个元素,但有本质区别。
v-if是惰性的,只是值为false就不会加载对应元素,为true才动态加载对应元素。
v-show:是无论为true和为false都会加载对应html代码,但为false时用display:none隐藏不在页面显示,但为true时页面上用display:block显示其效果。适用场景:切换频繁的场合用v-show,切换不频繁的场合用v-if
-
说一下vue自定义指令如何实现的和适用场景?
全局自定义指令:Vue.directive(‘指令名’,{ inserted(el) { } })
局部自定义指令:directives:{ } -
什么是mvvm?
MVVM是model-view-viewModel的缩写.是一种设计思想。Model层代表数据模型,用于定义数据修改和操作的业务逻辑;View代表UI组件,负责将数据模型转化为UI展现出来,ViewModel是一个同步View和Model的对象。
在MVVM架构下,View和我Model之间并没有知己饿的联系,而是通过ViewModel进行交互。 -
vue的优点是什么?
a. 低耦合:视图View可以独立于Model变化和修改,一个ViewModel可以绑定到不同给的“view”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
b. 可重用性:你可以把一些视图逻辑放在ViewModel里面,让很多view重用这段视图逻辑。
c.独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
d.可测试:界面素来是比较难测试的,而现在测试可以针对ViewModel来写。 -
vue之间是怎么传值的
-父组件与子组件传值
父组件通过标签上定义传值(:父组件名称=”子组件props的名称”)
子组件通过props的方式接受数据
-子组件向父组件传递数据
子组件通过$emit方法传递参数给父组件 -
v-show和v-if之间的区别
v-show指令是通过修改元素的display的CSS属性让其显示或隐藏。
v-if指令是直接销毁和重建DOM节点,达到让元素显示和隐藏的效果。 -
的作用是什么?
keep-alive标签包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。 -
指令v-el的作用是什么?
提供一个在页面上已存在的DOM元素作为Vue实例的挂载目标,可以是CSS选择器,也可以是一个HTMLElement实例。 -
为什么使用key?
当有相同标签名的元素切换时,需要通过key特性设置唯一的值来标记已让vue区分它们,否则vue为了效率只会替换相同标签内部的内容。 -
为什么要避免v-if和v-for一起使用?
当vue处理指令时,v-for比v-if具有更高的优先级,通过v-if移动到容器元素,不会再重复遍历列表中的每个值,取而代之的事,我们只检查它一次,且不会再v-if为否的时候运行v-for。 -
Vue的双向数据绑定原理是什么?
vue.js是才用数据劫持介个发布-订阅者模式的方法,通过object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 -
生命周期
生命总共分为8个阶段创建前/后、载入前/后、更新前/后、销毁前/后
创建前/后 : 在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据data有了,el还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,单还没有挂载之前都是虚拟的demo阶段,data.message还未替换.在mounted阶段,vue实例挂载完后,data.message成功渲染.
更新前/后:当data变化时,户触发beforeUpdata和updata方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经结束了事件监听以及和dom的绑定,但是dom结构依然存在。 -
怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
在router目录下的index.js文件中,对path属性加上/:id。
使用router对象的params id。 -
vuex的五大属性
Vue有五个核心概念:state、getters、mutations、actions、modules。
state => 基本数据。
getters => 从基本数据派生的数据。
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex。 -
不使用vuex有什么影响
1)可维性会下降,想修改数据要维护三个地方。
2)可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的。
3)增加耦合,大量的上传派发,会让耦合性大大增加。而Vue用Component就是为了减少耦合。
React部分:
1. react事件机制:
-
react不是给真实dom添加的事件,而是在document处监听了所有事件,运用冒泡原理,在document处,react将事件内容封装并交由真正的处理函数运行,这样不仅减少了内存的消耗,还能再组件销毁时统一订阅和移除事件。
冒泡到document上的事件也不是原生的浏览器事件,而是由react自己实现的合成事件,react中阻止事件冒泡,只能使用event.stopProppagation()方法,而不能使用event.preventDefault()方法 -
实现合成事件的目的:
- 合成事件首先抹平了浏览器之间的兼容问题,其次这是一个跨浏览器原生事件包装器,赋予了跨浏览器开发的能力
- 低于原生浏览器事件来说,浏览器会给监听器创建一个事件对象。如果有很多的事件监听,那就需要分配很多的事件对象,浪费内存。对于合成事件来说,有一个事件池专门来管理他们的销毁和创建,当事件需要被使用时,就会从池子中复用对象,事件回调结束后,就会销毁事件对象上的属性,从而便于下次复用事件对象
-
react事件和普通事件有什么不同
事件命名方式不同,原生事件为全小写,react事件采用小驼峰;
对于事件函数处理语法,原生事件为字符串,react为函数;
react事件不能采用return false的方式来阻止浏览器默认行为,而必须要明确的调用preventDefault()来阻止默认行为 -
react.component 和 react.purecomponent的区别
purecomponent表示一个纯组件,可以用来优化react程序,减少render函数执行的次数,从而提高组件的性能。purecomponent会自动执行shouldcomponetupdate函数。但是purecomponent中的shuldcomponentupdate进行的是浅比较,如果是医用数据类型的数据,只会比较引用地址。 -
react在render中能访问refs吗?为什么?
不能,因为render阶段dom还没有生成,无法获取dom,dom的获取需要在pre-commit阶段和commit阶段 -
类组件和函数组件的区别
相同点: 都可以接受属性并返回react元素
不同点:
(1)类组件需要创建实例,是基于面向对象的方式编程,函数组件不需要创建实例,基于函数编程的思想
(2)类组件需要创建并保持实例,会占用一定的内存,函数组件不需要创建实例,可以节约内存占用。
(3)类组件有完整的生命周期,函数组件没有生命周期。
(4)类组件通过shouldcomponent和purecomponent跳过更新,而函数组件可以通过react.memo跳过更新
(5)类组件复用逻辑一般用hoc,函数组件可以自定义hook。 -
setState是同步还是异步
(1)react生命周期中以及事件处理中,为异步。
(2)原生方法中是同步。 -
调用setState的时候,发生了什么?
react会将传入的参数对象与组件当前的状态合并,然后出发所谓的调和过程,经过调和过程,reaact会以相对高效的方式根据鑫的状态构建react元素树并着手重新渲染整个UI界面,在react得到元素树后,react会自动计算出新的树与老的树的节点差异,然后根据差异对界面进行最小化冲渲染。 -
什么时react的refs?为什么很重要?
refs允许直接访问DOM元素或者组件实例,也可以通过ref访问子组件的方法。
本质为ReactDOM.render()返回的组件实例,如果时渲染组件则返回的时组件实例,如果渲染dom则返回的时具体的dom节点。
如果该值是一个字符串,react将会在组件实例化对象的refs属性中,存储一个同名属性,改属性是对这个DOM元素的引用。可以通过原生的DOM API操作。
如何使用:
· 传入字符串,使用时通过this.refs.传入的字符串的格式获取对应的元素。
· 传入对象,对象是通过React.createRef()方式创建出来的,使用时获取到创建的对象中存在current属性就是对应的元素。
· 传入函数,该函数会在DOM被挂载时进行回调,这个函数会传入一个元素对象,可以自己保存,使用时,直接拿到之前保存的元素对象即可。
· 传入hook,hook时同故宫useRef()方式创建,使用时通过生成hook对象的current属性就是对应的元素。
应用场景
· 对DOM元素的焦点控制、内容选择、
· 对DOM元素的内容设置及媒体播放
· 对DOM元素的操作和对组件实例的操作
· 获取子组件中的方法等
-
setState第二个参数有什么用?使用它的目的是什么?
一个回调函数,当setState方法执行结束并重新渲染该组件的时候调用。
用于监听渲染是否完成。 -
vue和react的不同点
(1)react严格上针对的是mvc模式的view层,vue则是mvvm模式。
(2)操作dom的方式不同,vue使用的是指令操作dom,react是通过js进行操作。
(3)数据绑定不同,vue实现的是双向绑定,react的数据流动是单项的。
(4)react中的state是不能直接改变的,需要使用setState改变。vue中的state不是必须的,数据主要是由data属性在vue对象中管理的。 -
react性能优化的方案
(1)重写shouldComponentUpdate来避免不必要的操作。
(2)使用production版本的react.js。
(3)使用key来帮助react识别列表中所有子组件的最小变化。 -
简述state和props的理解,有啥区别
state:
· 组件数据来源之一,一般在constructor中初始化。
· 需要修改state时,需要调用setState。props: · 组件接收的从外部传入的参数。子组件中的props不可更改。 · 从父组件流向子组件。 相同点: · 两者都是js对象。 · 两者都可以用于保存数据。 · 都能出发render。
-
为什么虚拟DOM会提高性能
虚拟DOM是JS对象,时一个真实DOM的JS对象;虚拟DOM相当于在JS和真是DOM中加了一个缓存,利用DOM DIFF算法避免了没有必要的DOM操作,从而提高了性能, -
为什么react router中使用switch关键字
由于router和switch对于路由的渲染策略不同,对router来说,如果有的链接既可以被路由A匹配,又可以被路由B匹配,那么router会同时渲染
对于switch来说,它只会渲染符合条件的第一个路径,避免重复匹配。 -
生命周期:
一.初始化阶段
getDefaultProps:获取实例的初始化状态
getInitialState: 获取每个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的DOM节点
componentDidMount:组件真正在被装载之后
二.运行中状态
componentWillReceiverProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回false,接受数据后不更新,组织render调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新描绘
三.销毁阶段
componentWillUnmount:组件即将销毁
JS部分
-
ES6中箭头函数与普通函数的区别
(1)普通函数的声明在变量提升中是最高的,箭头函数没有函数提升。
(2)箭头函数没有this,arguments。
(3)箭头函数不能作为构造函数,不能被new,没有property。
(4)call和apply方法只有参数,没有作用域。 -
什么是闭包,有什么危害?
闭包就是一个定义在函数内部的函数。因为js中存在作用域的问题,所以在函数内部定义的变量在函数外部是没有办法直接获取到的。闭包可以实现函数属性和方法的私有化。
因为闭包会将内部变量存储在内存中,如果长时间不清除的话,会造成内存泄漏问题,影响程序的性能。 -
创建对象的方法
(1)字面量方式
const obj = {
name: 'obj',
eat:function(){
console.log('this is a obj')
}
}
(2)通过构造函数创建
const obj = new 函数名();
eg:
function Person(name, sex){
this.name=name;
this.age = sex;
this.job = function(){
console.log(this.name);
}
}
const child = new Person('guaiguai', '女');
Person.job();
(3)通过new关键字创建
const person = new Object();
person.name = 'xiaokuoai';
person.jon = function(){
console.log('xiaokuoai');
}
(4)工厂方式
function(name, age){
const stu = new Object();
stu.name = name;
stu.age = age;
stu.job = function(){
console.log(this.name+'学习...');
}
return stu;
}
- 判断对象是否拥有某一属性
(1)可以用in操作符
const obj = {
name: 'ming',
age: 12
};
'name' in obj; // true
'sex' in obj; // false
// 注意:如果obj的原型链上能找到其他属性,则in操作符返回为true(继承)
'toString' in obj; // true 继承得到的属性同样返回true
(2)hasOwnProperty() 可以判断一个属性是否是该对象自身拥有的
const owner = {
name: 'ow'
}
owner.hasOwnProperty('name'); // true
owner.hasOwnProperty('age'); // false
- Math
(1) Math.trunc() – 用于去除一个数的小数部分,返回整数部分。对于非数值它会内部调用Number方法先将其转换为数值。
(2) Math.sign() – 判断一个数是正数、负数、零或者NaN。对于非数值,会将其转换成数值。返回五种值:
a:参数为正数,返回 +1;
b:参数为负数,返回 -1;
c:参数为0,返回 0 ;
d:参数为-0, 返回-0;
e:其他值,返回NaN;
(3) Math.sqrt(x) – 求x的开平方
Math.sqrt(25); // 5
- (4)Math.pow(x,y) – 求x的y次方
-
Number
(1)isFinite();----检测是否是有限的数字,即不是Infinity。如果参数不是数字直接返回false。
(2)isNaN();----判断参数是不是NaN;
(3)parseInt();----将字符串转为整树;
(4)parseFloat();----将字符串转为浮点数;
(5)isInteger();----判断一个数值是否为整数【如果数字超过了小数点后面的十六个进制则会判断失误。因为超过的被遗弃了。或者绝对值小于js能判断的最小值也会失误被转为0】 -
string方法
(1)charAt(index) ---- 获取index位置处的字符
(2)charCodeAt(index)---- 获取index位置处字符的unicode编码
(3)string.fromCharCode(code) ---- 将unicode编码转换为对应的字符串
(4)concat() ---- 链接字符串
(5)lastIndexOf(sub) ---- 查找符合条件的第一个字符串所在下标(从后往前查)
(6)slice(start,end) ---- 截取子字符串
(7)subString(start,end)---- 截取子字符串,不包括endIndex
(8)split() ---- 切割字符串,将字符串以指定字符切割成数组
(9)replace(oldString,newString) ---- 替换
(10)trim() ---- 去掉前后空白
(11)includes(sub)---- 返回布尔值,表示是否找到参数字符串
(12)padStart() ---- 补全头部
(13)padEnd()----补全尾部4
(14)matchAll() ---- 返回一个正则表达式在当前字符串的所有匹配 -
JSON
(1)JSON.stringify() ---- 将js值转为JSON文本字符串
(2)JSON.parse() ---- 将json文本字符串转为js值
(3)encodeURIComponent() ---- 编码
(4)decodeURIComponent() ---- 解码 -
Array
(1)push() ---- 向原数组末尾添加元素,返回新长度,会改变原数组
(2)unshift()---- 向原数组开头添加元素,返回新长度,会改变元数组
(3)splice(index,howmany,value1,value2…)---- 新增/删除指定索引元素,改变原数组
(4)pop()---- 删除数组最后一位元素,返回被删除的元素,改变原数组
(5)shift()---- 删除头部元素,返回被删除的元素,改变原数组
(6)sort() ---- 排序,改变原数组,返回新数组
(7)concat() ---- 连接多个数组,返回新数组,不改变原数组
(8)join()---- 将数组的每个元素以指定分隔符连接成字符串,返回字符串
(9)slice(start,end) ---- 从start返回截取指定索引范围内的元素,如果不传值,则相当于直接拷贝了一份数组的值,end可以不传,表示截取到最后一位,start与end可以传负值,表示从后往前计数,返回新数组,不改变原数组
(10)toString()---- 转换为字符串,和不传参数的join一样,还可以使用2,8,16进制转变为不同结果
(11)flat()---- 数组降维,Infinity降至一维,不改变原数组,返回新数组 -
什么是原型链
所有的函数都有prototype属性
所有的对象都有__proto__属性
在js中,每个函数都有一个原型属性protorype指向自身的原型,而由这个函数创建的对象也有一个proto属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个proto指向自己的原型,这样逐层深入指导Object对象的原型,这样就形成了原型链。 -
JS的垃圾回收机制
(1)概述:
JS的垃圾回收机制是为了防止内存泄漏,垃圾回收机制就是不停歇的寻找这些不再使用的变量,并且释放掉它所指向的内存。
(2)变量的声明周期
当一个变量的生命周期结束后,它所指向的内存就会被释放。JS由两种变量,局部变量和全局变量,局部变量是在他当前的函数中产生作用,该函数结束之后,该变量内存会被释放,全局变量的话会一直存在,直到浏览器关闭为止。
(3)JS垃圾回收方式
由两种方式:标记清楚、引用计数
标记清除:当变量进入执行环境(声明变量)的时候,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,将其在度标记,随之进行删除
引用计数:跟踪某一个值的引用次数,当声明一个变量并且将一个引用类型赋值给变量的时候引用次数加1,当这个变量指向其他一个时引用次数减1,当为0时触发回收机制进行回收。 -
Async和Await如何通过同步的方式实现异步
async/await时Generator的语法糖,就是一个自执行的Generate函数,利用generate函数的特性把异步的代码写成“同步”的形式。 -
setTimeout、Promise、Async/Await 的区别
setTimeout属于宏任务,Promise里面的then方法属于微任务,Async/await中await语法后面紧跟的表达式是同步的,但接下来的代码是异步的,属于微任务。
Promise本身是同步的,但在执行resolve或者rejects是异步的,即then方法是异步的。 -
说说JS作用域
JS作用域也就是JS识别变量的范围,作用域链也就是JS查找变量的顺序。 JS作用域主要包括全局作用域、局部作用域和ES6的块级作用域。 全局作用域:也就是定义在window下的变量范围,在任何地方都可以访问。 局部作用域:是只在函数内部定义的变量范围 块级作用域:简单来说用let和const在任意的代码块中定义的变量都认 为是块级作用域中的变量,例如在for循环中用let定义的变量,在if语句中用let定义的变量等等。 **注:尽量不要使用全局变量,因为容易导致全局的污染,命名冲突,对bug查找不利。**
-
深拷贝,浅拷贝
浅拷贝: 直接赋值,Object.assign({},{})
深拷贝:递归,Object.assign({},{}) -
this指向问题:
- this总是直接指向函数的调用者
- 如果有new关键字,this指向new出来的对象
- 在事件中,this指向事件的调用者
- 在计时器中,this的指向是windows
- 箭头函数中,this总是指向上一个作用域 -
箭头函数和普通函数的区别
- 函数体内的this对象,就是定义时所在的对象,而不是调用时所在的对象
- 可以当作构造函数(不能使用new字符);
- 该函数内没有arguments对象,如果需要使用,可以使用rest代替
- 不能使用yeild命令,因此肩头函数不能被用作Generator函数
其他
-
sass和less的区别
定义变量的符号不同,less是用@,sass是用$
变量的作用域不同,less在全局定义,就作用在全局,在代码块中定义,就作用于整个代码块。而sass只作用于全局。
编译环境不同,less在开发者环境编译,sass在服务器环境下编译。 -
如何解决跨域
(1)jsonp
(2)document.domain + iframe
(3)nodejs中间件代理跨域
(4)后端在头部信息里面设置安全域名 -
项目性能优化
(1)减少HTTP请求次数
(2)减少DNS查询
(3)使用CDN
(4)避免重定向
(5)图片懒加载
(6)减少DOM元素元素数量
(7)减少DOM操作
(8)使用外部JS和CSS
(9)压缩JS、CSS、字体、图片等
(10)优化CSS Sprite
(11)使用iconfont
(12)尽量减少iframe的使用
(13)避免图片src为空
(14)把JS放在页面底部
思维导图:
-
浏览器中输入url到网页显示,整个过程发生了什么
DNS域名解析
建立tpc ip协议,发送http请求
服务器端响应http请求,浏览器得到html代码
浏览器解析html代码,并请求html代码中的资源
浏览器对页面进行渲染呈现给用户 -
安全性问题
(1)XSS攻击:注入恶意代码
- cookie设置httpOnly
- 转义页面上的输入内容和输出内容
(2)CSRF:跨站请求伪造,防护:
- get不修改数据
- 不被第三方网站访问到用户的cookie
- 设置白名单,不被第三方网站请求
- 请求校验 -
CDN
- 什么是CDN?
-
是一组分布在各个地区的服务器。这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户距离近,来满足数据的请求。CDN提供快速服务,较少受高流量影响。
- 为什么要用CDN?
-
提升响应速度
-
实现0.5px的实线
(1){ height: 1px; transform: scaleY(0.5); transform-origin: 50% 100%; }
(2)boxshadow方法(safari不支持)
{
height: 1px;
background: none;
box-shadow: 0 0.5px 0 #000;
}
(3)svg(firefox不支持)
{
background: none;
height: 1px;
background: url("data:image/svg+xml;utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='1px'><line x1='0' y1='0' x2='100%' y2='0' stroke='#000'></line></svg>");
}
svg文件:
<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='1px'>
<line x1='0' y1='0' x2='100%' y2='0' stroke='#000'></line>
</svg>