1、canvas和svg的区别
canvas
- 基于像素
- 单个html,类似画笔在画布上画画
svg
- 基于对象模型
- 多个图形元素
- 高保真(不失真,不变形)
2、vdom
- 用 js 来模拟 DOM 结构
- dom 变化的对比,放在js层来执行
- 提高重绘性能
- DOM操作比较占内存,将dom操作放在js层,可以提高效率性能
3、数组的方法
- push(),末尾添加元素,会返回改变后数组的长度
- pop 删除最后一个,返回被删除的值
- concat 连接两个或多个数组,返回一个新数组
- shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
- unshift:将参数添加到原数组开头,并返回数组的长度
- splice 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。
3.1 es6数组方法
-
map // 循环,必须有return 不设就返回undefined
-
forEach // 循环
-
find // 找到第一个符合的,找到之后就会直接返回
-
filter // 根据条件过滤
-
every // 要所有的满足才可以
-
some // 只要有一个满足就行
-
reduce // reduce(function(sum,number){…},0)要有两个参数,第一个参数一定要初始化
// 结果值是1+2+3+4+5 = 15
4、jsonp
- jsonp是一个简单高效的跨域方式,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。
- 特点:不受同源策略的限制,兼容性更好,易于实现,只支持get。
5、IE盒子模型和谷歌的区别
- W3C的盒模型方式被称为“
content-box
” - IE的被称为“
border-box
” box-sizing: border-box;
就是为了在设置有padding值和border值的时候不把宽度撑开。
6、js原型、原型链
- 万物皆对象,万物皆空(js中大部分都是对象, 对象的源头为null)
- 原型:保存所有子对象的共有属性值和方法的父对象,分为隐式原型
__proto__
和显示原型prototype,隐式原型指向他构造函数的显示原型 - 原型链:由各级子对象的
__proto__
属性连续引用形成的结构 - 主要三个属性:
__proto__
、constructor
、prototype
总结:
.prototype
只是一个指针,指向的是原型对象- 对象的prototype.constructor就是对象本身
Object.prototype.constructor==Object
- 隐式原型等于构造函数的原型
__proto__ = constructor.prototype
- 原型链的尽头一般都是
Object.prototype
Object.prototype.__proto__
为null- 原型链指原型与原型层层相连接的过程即为原型链,访问一个对象的属性,这对象内部不存在这个属性就会去它的原型对象中找,一直找下去,就是原型链的概念。
图解:
funtion对象和Object对象之间的关系:
- Function是顶层的构造器 Object是顶层的对象
- 顶层现有null,Object.prototype,Function.prototype Function
- 原型上说:Function继承了Object toString
- 构造器上说:Function构造了Object new Object()
7、prototype和__proto__的区别
-
prototype
是函数才有的属性,比如你创建一个对象,它是没有prototype属性的
-
__proto__
是每个对象都有的属性,是js内部属性(不推荐使用) -
__proto__ = constructor.prototype
也就是说它等于构造函数的原型 -
接上一条:但是通过
Object.create()
创建的对象有可能不是, Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
8、js防抖、节流
- 防抖节流的作用都是用于防止函数被多次调用,
- 区别在于,如果一个用户一直触发这个函数,每次触发的间隔都小于wait,防抖的情况下只会调用一次,而节流的情况会每隔一段一段时间调用函数
- 防抖在间隔时间内被触发会重新计时,执行最后一次
- 节流在间隔时间内只执行一次,第一次
9、跨域问题
-
jsonp跨域
JSONP(JSON with Padding:填充式JSON),应用JSON的一种新方法, -
JSON、JSONP的区别:
1、JSON返回的是一串数据、JSONP返回的是脚本代码(包含一个函数调用)
2、JSONP 只支持get请求、不支持post请求
(类似往页面添加一个script标签,通过src属性去触发对指定地址的请求,故只能是Get请求) -
nginx反向代理:
-
服务端端修改header
header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
10、es6新数据类型symbol
- symbol是es6新推出的一种基本数据类型,表示独一无二的值。最大用途就是用来定义对象唯一的属性名
11、ajax实现
创建XMLHttpRequest对象。
设置请求方式。
调用回调函数。
发送请求。
//第一步:创建XMLHttpRequest对象
var xmlHttp;
if (window.XMLHttpRequest) { //非IE
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) { //IE
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
}
//第二步:设置和服务器端交互的相应参数,向路径http://localhost:8080/getAjax准备发送数据
var url = "http://localhost:8080/getAjax";
xmlHttp.open("POST", url, true);
// open(method,url,async) post/get
// .send(string) 仅用于post
//第三步:注册回调函数
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var obj = document.getElementById(id);
obj.innerHTML = xmlHttp.responseText;
} else {
alert("AJAX服务器返回错误!");
}
}
}
//第四步:设置发送请求的内容和发送报送。然后发送请求
var params = "userName=" + document.getElementsByName("userName")[0].value + "&userPass=" + document.getElementsByName("userPass")[0].value + "&time=" + Math.random(); // 增加time随机参数,防止读取缓存
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); // 向请求添加 HTTP 头,POST如果有数据一定加加!!!!
xmlHttp.send(params);
12、call、apply、bind
- 作用:改变this的指向
- 第一个参数都是this的指向
- call/apply直接返回结果,立即执行的,bind返回的是一个函数,需要再次调用
- call/bind,第一个参数是this,后面跟参数列表。apply两个参数,第二个参数接收一个数组
- 都是Function对象上的方法
13、react render之后发生了什么
- 1、React创建元素,解析组件标签,找到MyComponent 组件
- 2、发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
- 3、将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
14、react高阶组件
- 定义:高阶组件(Higher Order Component,HOC)并不是React提供的某种API,而是使用React的一种模式,一个高阶组件就是一个函数,这个函数接受一个组件作为输入,然后返回一个新的组件作为结果,例如:Redux 的 connect
- 意义:1、重用代码。2、修改现有react组件的行为
- 实现方式:
1、代理方式的高阶组件
2、继承方式的高阶组件
15、this.setState可以放在constructor中吗
- 直接放在constructor中不会报错,但是也不会生效
- 原因:this.setState( )本身是异步的,类似于是一种请求而不是立即更新组件的命令,为了更好的性能,React会延迟调用它,不会保证state的变更会立即生效,而是会批量推迟更新
constructor(props){
super(props)
this.state = {
name:'qss'
}
this.setState({
name:'qss3'
})
}
- 配合settimeout会生效,官方建议放在componentDidUpdate中执行或利用回调函数(setState(updater, callback))
constructor(props){
super(props)
this.state = {
name:'qss'
}
setTimeout(()=>{
this.setState({
name:'qss3'
})
},1000)
}
16、redux
- 如果UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。
- redux取值,在需要使用store中的状态值得组件导出的时候,使用connect
例如:export default connect(组件名)
,组件中可直接使用,this.props.状态名
来使用 - 链接https://blog.csdn.net/sinat_41904410/article/details/102961499
17、vue和react的区别
-
vue 提供了一系列的api, 而react的api 很少
-
vue的思想是响应式的,也就是基于是数据可变的,实现了数据的双向绑定,react整体是函数式的思想,是单向数据流,推崇结合immutable来实现数据不可变
-
vue 采用了template, react采用了jsx (本质上都是模版)
-
React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果做脏检查。
-
Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。
18、vuex的相关属性、vuex的模块化
state, getters, mutations, actions, modules。
1. state:vuex的基本数据,用来存储数据
2. getters:获取数据的,this.$store.getters.xxx
3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
同步操作数据:this.$store.commit(“方法名”,数据)
4. action:和mutation的功能大致相同,异步更新数据,this.$store.dispatch(“方法名”,数据)
不同点:
1. Action 提交的是 mutation,而不是直接变更状态。
2. Action 可以包含任意异步操作。
5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
19、vue父子组件传值,兄弟组件之间的传值
- 父传子,属性形式传递,props接收
- 子传父,函数形式,使用$emit() 调用父级函数传递
- 兄弟组件之间传值,也是通过$emit;
原理是:vue一个新的实例,类似于一个站,连接着两个组件,也就是一个中央事件总线;eventBus
19.1、父子组件生命周期执行顺序
-
加载渲染过程(父beforeMount之后开始执行子组件的生命周期)
-
更新过程
-
销毁过程
只销毁子组件
销毁父组件同时销毁子组件
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
- 常用钩子简易版
父create->子created->子mounted->父mounted
20、webpack/gulp
- webpack核心代码
- Webpack有人也称之为 模块打包机
- Webpack更侧重于模块打包,当然我们可以把开发中的所有资源(图片、js文件、css文件等)都可以看成模块,最初Webpack本身就是为前端JS代码打包而设计的,后来被扩展到其他资源的打包处理。Webpack是通过loader(加载器)和plugins(插件)对资源进行处理的。
const path = require('path');
var webpack = require("webpack");
const config = {
entry: {
main: './src/index.js'
},
output: {
filename: '[name]-[hash:8].js',
path: path.join(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.html/, use: ['html-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: __dirname + '/index.html'
})
]
}
module.exports = config;
- gulp核心代码
- Gulp侧重于前端开发的 整个过程 的控制管理(像是流水线)
- 通过给gulp配置不通的task(通过Gulp中的gulp.task()方法配置,比如启动server、sass/less预编译、文件的合并压缩等等)来让gulp实现不同的功能,从而构建整个前端开发流程。
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('hello', function() {
// 将你的默认的任务代码放在这
console.log('hello world!');
});
gulp.task('sass',function(){
return gulp.src('src/main/webapp/static/styles/scss/apply.scss')
.pipe(sass())
.pipe(gulp.dest('src/main/webapp/static/styles/css'))
});
21、webpack loader和plugins
1、loader:
- loader从字面的意思理解,是 加载 的意思。
- loader是运行在NodeJS中。
- 由于webpack 本身只能打包commonjs规范的js文件,所以,针对css,图片等格式的文件没法打包,就需要引入第三方的模块进行打包。css-loader和style-loader模块等等
- loader运行在打包文件之前(loader为在模块加载时的预处理文件)
2、plugin
- 也是为了扩展webpack的功能
- plugin 是作用于webpack本身上的。
- 针对html文件打包和拷贝(还有很多设置)的插件:html-webpack-plugin。
- plugins在整个编译周期都起作用。
22、闭包
-
闭包就是可以访问函数内部参数的函数,闭包的本质是作用域,用于保护和保存局部变量,保护局部变量不受污染,保存循环中的i值
-
优点是:避免全局变量污染,变量一直存在在内存中
-
缺点是:变量一直存在在内存中,如果使用不当会导致内存泄漏,需要在退出函数时将不用的参数删除
应用: 给对象循环添加点击事件的时候,由于函数内部是单独作用域,
如下第一种写法,返回值是当循环结束之后的 i 值,是333
第二种写法应用闭包,实现数据的驻留,打印结果为 012
var btns = [{name:'b1'},{name:'b2'},{name:'b3'}]
// 未应用闭包
function bind(){
for(var i = 0;i<btns.length;i++){
btns[i].onclick=function(){
console.log(i)
}
}
}
// 应用闭包,增加立即执行函数
function bind(){
for(var i = 0;i<btns.length;i++){
(function (num){
btns[i].onclick=function(){
console.log(num)
}
})(i)
}
}
// 第三种作为扩展介绍,es6的let,let会形成单独作用域
function bind(){
for(let i = 0;i<btns.length;i++){
btns[i].onclick=function(){
console.log(i)
}
}
}
bind();
btns[0].onclick();
btns[1].onclick();
btns[2].onclick();
22.1、执行环境(执行上下文)
执行环境(EC execution context)和作用域概念类似,分为全局执行环境、局部执行环境
- 全局执行环境,也就是window
- 局部执行环境指的是函数内部执行环境
浏览器环境栈:
- 默认有一个全局执行环境 ,也就是window
[ window ] - 当我们创建的函数被调用的时候,形成了一个新的局部执行环境,栈是先进后出的理念,这个时候window执行环境会被挤入栈底
[ fun, window ] - 多个环境调用的时候依次,执行的时候如果在第一层没有找到对应属性,就往上查找,栈中方法调用之后内存会被自动释放,保留变量,就比如闭包上面的那个例子,为什么不用闭包的时候,调用方法返回的值是3,因为当找到那一层执行环境的时候 i 已经结束了循环,值为3
[ fun, fun, window ]
图解:
23、vue中template里面的和render里面的区别是啥
-
相同之处:
render 函数 跟 template 一样都是创建 html 模板 -
不同之处:
1、Template适合逻辑简单,render适合复杂逻辑。
2、使用者template理解起来相对容易,但灵活性不足;自定义render函数灵活性高,但对使用者要求较高。
3、render的性能较高,template性能较低。这一点我们可以看一下,下图中vue组件渲染的流程图可知。
4、基于上一点,我们通过vue组件渲染流程图知道,使用render函数渲染没有编译过程,相当于使用者直接将代码给程序。所以,使用它对使用者要求高,且易出现错误
5、Render 函数的优先级要比template的级别要高,但是要注意的是Mustache(双花括号)语法就不能再次使用
24、vue双向绑定的原理
- 通过
object.defineProperty()
来劫持各个属性的setter/getter
,在数据变动时,发布消息给订阅者,触发相应的监听回调
Object.defineProperty(obj,prop,descriptor){}
// 参数描述
// obj:需要定义属性的对象
// prop:需要定义的属性
// descriptor: 属性的描述描述符
// 返回值: 返回此对象
var obj = {};
let descriptor = {
// 数据描述符
configurable:false,// 表示该属性能否通过delete删除,能否修改属性的特性或者能否修改访问器属性,默认为false.当且仅当该属性的configurable 为true的时候,才能实现上述行为
writable:false,// 表示该属性的值是否可写,默认为false.当且仅当属性的writable为true时,其值才能被赋值运算符改变
enumerable:false, // 表示该属性是否可以枚举,即是否可以通过for..in访问属性,默认为false
value:'hello world' // 表示该属性的值,可以是任何有效的js值,默认为undefined
// 访问器描述符:数据描述符和访问器描述符不能同时使用
// get:在读取属性时调用的函数,默认为undefined
// set:在写入属性时调用的函数,默认值为undefined
}
Object.defineProperty(obj,'qwe',descriptor)
console.log(obj.qwe) // hello world
数据响应式 vue
function definReactive(obj, key, val){
// 在此作用域内存在一个val变量,由于闭包的存在他不会被销毁,会一直保存在内存中
Object.defineProperty(obj,key,{
get (){ //获取key上的值
console.log('get',key)
return val
},
set(newval){
if(newval !== val){
console.log('set',key)
val = newval
}
}
})
}
const obj = {}
definReactive(obj,'foo','123') // 操作对象obj
obj.foo // 触发get函数
obj.foo = '456' //触发set函数,此时newval = 456,而val由于闭包还是123
console.log(obj)
25、keep-alive 触发的生命周期
-
当引入keep-alive的时候,页面第一次进入,钩子的触发顺序
created-> mounted-> activated
,退出时触发deactivated
。当再次进入(前进或者后退)时,只触发activated
。 -
事件挂载的方法等,只执行一次的放在
mounted
中;组件每次进去执行的方法放在activated
中;
26、computed/watch、computed可以监听单个属性吗?
- computed 是计算属性,监听多个属性,影响一个值,例如购物车结算
- watch 监听单个属性,一条数据影响多条数据,例如数据搜索
- computed 可以监听单个属性,使用get () {}, 来获取单个值
computed: {
// 多个值,影响一个值
evidenceHeight () {
let height = this.$store.state.common.documentClientHeight - 350
return {minHeight: height + 'px'}
},
// 单个值
defaultTheme: {
get () {
return this.$store.state.config.defaultTheme
},
set (val) {
return this.$store.commit('config/updateDefaultTheme', val)
}
}
},
watch: {
// 普通监听
value () {
if (this.value === '') {
this.clearHandle()
}
},
// 深度监听
files: {
handler (files) {
if (files && files.length > 0) {
this.accessories = files
this.selectedAccessoriesCount = files.length
}
},
immediate: true, // 立即执行 :当刷新页面时会立即执行一次
deep: false // 复杂类型深度监听
},
}
27、require 和 import 区别
- 模块加载时间:require运行时动态加载、import在编译时静态加载(效率更高,需要放在顶部)
- 使用位置:require可以在函数、判断语句等代码块中加载,import必须在顶部加载
- 等等
28、new 一个函数相关
1.新创建一个空对象
var fn = new Object();
2.把fn的proto指向构造函数的prototype对象,实现继承
Fn.prototype = fn.__proto__
3.通过调用call、apply方法执行构造函数并改变this对象(绑定到实例对象上,将 fn 作为 this 的上下文)
Fn.call(f)
4.如果没有手动返回其他任何对象或返回值是基本类型(Number、String、Boolean)的值,会返回 this 指向的新对象,也就是实例,若返回值是引用类型(Object、Array、Function)的值,则实际返回值为这个引用类型。
示例:
function myNew (fun) {
return function () {
// 创建一个新对象且将其隐式原型指向构造函数原型
let obj = {
__proto__ : fun.prototype
}
// 执行构造函数
fun.call(obj, ...arguments)
// 返回该对象
return obj
}
}
function person(name, age) {
this.name = name
this.age = age
}
let obj = myNew(person)('li', 18)
29、深拷贝,浅拷贝区别,
- 浅拷贝是复制原对象,共享一个内存,修改的话会影响原对象的值,常见的浅拷贝方式:遍历,Object.assign
- 深拷贝会创建一个一模一样的对象,不共享内存,修改互不影响
- 深拷贝函数的思路(遍历):
1、判断目标是对象还是数组,初始赋值{} || []
2、for in 遍历目标
3、hasOwnProperty() 判断当前值是否存在
4、判断是否是对象,否,直接赋值,是,判断当前对象是对象还是数组,再次调用拷贝函数
26、JSON.parse(JSON.stringfy)进行深拷贝有啥弊端
- obj里的时间对象new Date()会被改为字符串形式,而不再是时间对象
- obj里有RegExp、Error对象,会得到空对象
- obj里有函数,undefined、symbol 会丢失
- obj里有NaN、Infinity和-Infinity,会变为null
- JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
30、判断数据类型的几种方式:instanstof、typeof、Object.prototype.toString.call()
- instanceof 用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上。通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。判断一个对象是否是另一个对象的实例
[] instanceof Object // true
[] instanceof Array // true
-
typeof 判断类型 但不能判断null,
-
最有效的判断类型方法:Object.prototype.toString.call(null)
-
indexof 查找给定元素在数组中的索引,没有的话返回-1,
[1,2].indexOf(2)
31、react生命周期
- 组件的生命周期可分成三个状态:
Mounting
:已插入真实 DOM
Updating
:正在被重新渲染
Unmounting
:已移出真实 DOM - react16,生命周期
componentWillMount
在渲染前调用
componentDidMount
在第一次渲染后调用(适合调用接口发起请求)
componentWillReceiveProps
在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate
返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate
时不被调用。可以在你确认不需要更新组件时使用。
componentWillUpdate
数据变化尚未更新前
componentDidUpdate
更新后
componentWillUnmount
卸载后
forceUpdate就是重新render。有些变量不在state上,但是你又想达到这个变量更新的时候,刷新render;或者state里的某个变量层次太深,更新的时候没有自动触发render。这些时候都可以手动调用forceUpdate自动触发render。
-
react16.4中新的生命周期
1、getDerivedStateFromProps(nextProps, prevState)
代替了旧的componentWillReceiveProps
及componentWillMount
代替原因:- getDerivedStateFromProps 中禁止了组件去访问 this.props,比较 nextProps 与 prevState 中的值,根据当前的 props 来更新组件的 state,而不是去访问this.props。
- 当state需要从props初始化时,使用
- 每次render都会调用
2、
getSnapshotBeforeUpdate(prevProps, prevState)
代替了旧的componentWillUpdate
- getSnapshotBeforeUpdate会在最终的 render 之前被调用,读取到的 DOM 元素状态是可以保证与componentDidUpdate 中一致的。
- 在 React 开启异步渲染模式后,在执行函数时读到的 DOM 元素状态并不总是渲染时相同,这就导致在 componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
32、vue生命周期
- created 、beforeMount 、mounted 这三个生命周期中可以请求数据
- beforeCreate 实例创建前(无data、无methods、无$el)
- created 实例创建后 (有data/methods,无$el)
- beforeMount 模板加载前
- mounted 模板加载后 (有$el,可以操作DOM了)
- beforeUpdate 数据更新后,对应的组件重新渲染之前
- updated 数据更新后,对应的组件重新渲染之后
- beforeDestory 组件销毁前,实例尚未销毁
- destoryed 组件销毁后,实例销毁
- activated 组件激活(keep-alive)组件触发
- deactivated 组件停用
33、web常见安全问题及解决方法
1、xss 跨站脚本攻击
- 使用encode方法将<等转换为代码
- 设置
HTTP Header
中的Content-Security-Policy
2、crsf 跨站请求伪造
- 加上token用于验证
- 设置cookie不随请求发送
3、sql注入
- 不要相信用户输入的信息,对其进行校验,加密敏感信息
更多安全问题可以看这个博文:https://blog.csdn.net/sinat_41904410/article/details/118254355?spm=1001.2014.3001.5502
34、前端性能提升
- 使用缓存
- 减少http请求
- 减少dom操作
- 图片懒加载
- css/js放置位置,css前,js后
35、Restful标准
- REST 指的是一组架构约束条件和原则。
- RESTful,满足rest原则的应用程序或设计就是 RESTful。
- RESTful架构是对MVC架构改进后所形成的一种架构,通过使用事先定义好的接口与不同的服务联系起来。在RESTful架构中,浏览器使用POST,DELETE,PUT和GET四种请求方式分别对指定的URL资源进行增删改查操作。因此,RESTful是通过URI实现对资源的管理及访问,具有扩展性强、结构清晰的特点。
- 为什么需要restful?
url具有很强可读性,具有自描述性
规范化请求过程和返回结果
资源描述与视图的松耦合
可提供openAPI,便于第三方系统集成,提高互操作性
提供无状态的服务接口,降低复杂度,可提高应用的水平扩展性
36、webpack性能优化
- 时间指的是打包时间尽可能快;空间指的是打包体积尽可能小
- 使用一些插件、配置来实现
时间:
- 缓存 babel-loader
- 缓存不常变动模块(代码分割,将不常改动的缓存起来)
- JS 与 CSS 并行加载
- 使用 HappyPack 插件对 Loader 进行多线程打包
- 使用 DNS 加载静态数据
空间:
- css压缩
- js压缩
37、css设置黑白条背景
- 使用css渐变属性,配合宽高呈现横向黑白条或者竖向黑白条
// 横向
height:25%;
background-image: linear-gradient(to bottom, #000 50%, #FFF 0);
// 竖向
width:25%;
background-image: linear-gradient(to bottom, #000 50%, #FFF 0);
38、div盒子里小盒子宽高固定从左到右排列,两边靠边,中间间隔相等,怎么布局
- float 计算对应的宽高
- 待解决
<div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
<div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
</div>
39、v-for和v-if为什么不能同时使用
因为v-for优先级比v-if高,每次判断都要先循环一遍,消耗性能较大,不建议同时使用
40、面向对象
面向对象概念: 就是把任何的数据和行为抽象成一个形象的对象,类似于人生活中思考的方式
类:对象(object)的模板,定义了同一组对象(又称实例)共有的属性和方法
就比如,车类:共有的属性:轮胎,发动机… 方法:发动
对象:属性:轮胎, 方法就是发动
就类似于java中的class概念
js中是没有类的概念的,我们可以通过构造函数形式实现面向对象
创建一个构造函数: function Person(){}
实例化 : new Person
js面向对象主要有三特点:
- 继承:子继承父
- 封装:就是将一些共有方法封装起来,方法: run:function(){}
- 多态:同一个东西在不同情况下的表现不同状态,有两个概念
- 重载:也就是说根据传入参数不同进行不同的处理计算
- 重写:也就是继承,比如子觉得父的run方法达不到自己预期,可以重写一个run1方法,也可以写run方法将父的run覆盖
41、继承
js继承的方式6种
- 简单原型链:类式继承
- 借用构造函数:缺点=》父类的原型方法自然不会被子类继承
- 组合继承(常用):类式继承+构造函数式继承
- 寄生组合继承(最佳):寄生式继承+构造函数式继承
- 原型式:跟类式继承一样,父类对象中的值类型的属性被复制,引用类型的属性被共有
- 寄生式:通过在一个函数内的过渡对象实现继承并返回新对象的方式
42、vue-router有哪几种钩子函数
beforEach
- 参数有
- to(Route路由对象)
- from(Route路由对象)
- next(function函数) 一定要调用才能进行下一步
afterEach
beforeRouterLeave
43、vue 中key的作用
key主要用在虚拟Dom算法中,每个虚拟节点VNode有一个唯一标识Key,通过对比新旧节点的key来判断节点是否改变,用key就可以大大提高渲染效率
44、diff算法
diff算法是指对新旧虚拟节点进行对比,并返回一个patch对象,用来存储两个节点不同的地方,最后利用patch记录的消息局部更新DOM
45、虚拟DOM的优缺点
缺点:首次渲染大量DOM的时候因为多了一层虚拟DOM计算,所以插入速度会比innerHTML慢
优点:使用js来模拟DOM,减少了DOM操作,减少了回流与重绘。提升性能。局部更新。
重绘指的是颜色等改变不影响布局,回流指的是布局改变,消耗性能较大
重绘不一定引起回流,回流一定会引起重绘
46、vue中的nextTick
在下次DOM更新循环结束之后执行延迟回调。在修改数据后,立即使用这个方法可以拿到更新后的DOM
应用:
- 想要在Vue生命周期函数中的created()操作DOM可以使用Vue.nextTick()回调函数
- 在数据改变后要执行的操作,而这个操作需要等数据改变后而改变DOM结构的时候才进行操作,需要用到nextTick
47、>>>、/deep/、::v-deep区别
- 都是深度选择器,可以对组件内部样式修改
- 原生css可用
>>>
表示深度选择 - 使用scss less等预处理器的话,
>>>
可能无法编译,需要使用::v-deep
、/deep/
, - 在scss中使用
/deep/
会报loader错误,这时可以使用::v-deep
来代替