[TOC]

js问题整理

1.变量提升

变量提升就是,在变量的作用域内,不管变量在何处声明,都会被提升到作用域的顶部,但是变量初始化的顺序不变。(注意,变量提升只将声明部分提升,赋值部分不改变位置)

这句话是什么意思呢?举个例子:
``function test() {
a=1;
b=2;
c=3
var a,b,c;
console.log(a);
console.log(b);
console.log(c);
}

这样一段代码,a , b, c三个变量是先赋值后声明,竟然没有报错。那是因为,按照变量提升的原则,在代码执行前,js编译器会将代码改成这样:

function test() {
var a,b,c;
a=1;
b=2;
c=3
console.log(a);
console.log(b);
console.log(c);
}
将变量提升到该作用域的最顶端声明,然后再按顺序执行其他的代码。
Exemple:

再举个例子帮助你理解变量提升。

var value="nihao";<br />    function test() {<br />    console.log(value);<br />    var value="byebye";<br />    }<br />    test();<br />这段代码输出的是undefined,你可能会疑惑,为什么没打印全局变量value?那是因为,根据变量提升的原则,js会将这段代码改成以下代码:<br />var value="nihao";
<br />function test() {<br />var value;
<br />console.log(value);
<br />value="byebye";
<br />}
   <br />test();<br />  <br />js会将作用域中的变量的声明放到作用域最顶部,这样打印value时,就近查找找到了value,所以不会再找全局的变量了,但此时value没有赋值,所以打印了undefined。

函数和变量都提升时,谁提到前面谁提到后面

在作用域中,不管变量和函数写在什么位置,所有变量会被整体提升到作用域顶部,所有函数也会被整体提升到作用域顶部,但是函数整体在变量整体的后面。[

](https://blog.csdn.net/baidu_33295233/article/details/79111309)

2.作用域

es5中只有全局作用域和函数作用域,es6新增了块级作用域。
var v = “hello”;
if(true){
console.log(v);
var v = “world”;
}

块级作用域

es6允许块级作用域的任意嵌套。外层作用域无法读取内层作用域的变量。内层作用域可以定义外层作用域的同名变量。
es6也规定,函数本身的作用域,在其所在的块级作用域之内。
块级作用域外部,无法调用块级作用域内部定义的函数。
块级作用域内let和const命令所声明的变量,只在命令所在的代码块内有效。
https://blog.csdn.net/u012982629/article/details/80515328

var与let、const的区别

1.var声明变量存在变量提升,let和const不存在变量提升
2.let、const都是块级局部变量
顾名思义,就是只在当前代码块起作用
3.同一作用域下let和const不能声明同名变量,而var可以

const 的特性和 let 完全一样,不同的只是:
1.const声明时候必须赋值;
2.只能进行一次赋值,即声明后不能再修改
3.如果声明的是复合类型数据,可以修改其属性

3.this指向,修改this指向方法

this指向:

This指向分为四种绑定规则:默认绑定、隐式绑定、显式绑定以及关键字new绑定。在ES6之后,又有了箭头函数中的this规则。
普通函数只要记住this 永远指向调用它的对象,new的时候,指向new出来的对象。
箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this。

改变this指向方法:

call()
第一个参数:this指向
call 方法的参数,应该是对象obj,如果参数为空或null,undefind,则默认传参全局对象
apply()
apply 方法的参数,应该是数组,如果参数为空或null,undefind,则默认传参全局对象
bind()
bind 用于将函数体内的this绑定到某个对象,然后返回一个新函数
通过new实例改变
新实例具体创建步骤:

  1. 构造函数作用域赋值给新对象(this就指向了该新对象)
  2. 执行构造函数中的代码(为新对象添加属性)
  3. 返回新对象

4.原生的去重

1.利用 ES6的set 方法

function unique(arr){
//Set数据结构,它类似于数组,其成员的值都是唯一的
return Array.from(new Set(arr));
// 利用Array.from将Set结构转换成数组
}
var arr = [1,2,2,3,5,3,6,5];
var res = unique(arr) console.log(res );

2.利用对象的属性不能相同的特点进行去重(推荐使用)

实现思路:
1.创建一个新的数组存放结果
2.创建一个空对象
3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。

说明:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。
function unique(arr){
var res = [];
var obj = {};
for(var i=0; i if( !obj[arr[i]] ){
obj[arr[i]] = 1;
res.push(arr[i]);
}
}
return res;
}
var arr = [1,2,2,3,5,3,6,5];
var res = unique(arr);
console.log(res );

5.js实现异步编程的4种方式

https://www.cnblogs.com/goloving/p/9393541.html

一、回调函数

这是异步编程最基本的方法。
假定有两个函数f1和f2,后者等待前者的执行结果。
回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合)(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

二、事件监听

另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
实现原理也是利用定时器的原理去把f1放入事件队列里,等全部执行完毕之后,才会执行事件队列里的方法

三、发布/订阅

四、Promises对象

目的是为异步编程提供统一接口

简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
比如,f1的回调函数f2,可以写成:f1().then(f2);

f1要进行如下改写(这里使用的是jQuery的实现

function f1(){
var dfd = $.Deferred();
setTimeout(function () { // f1的任务代码
dfd.resolve();
}, 500);
return dfd.promise;
}

这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。

比如,指定多个回调函数:f1().then(f2).then(f3);
再比如,指定发生错误时的回调函数:f1().then(f2).fail(f3);
而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。
我的理解其实就是执行f1返回的一个promise,内部也是通过定时器去将f1的耗时很久的代码放入事件队列里,不阻塞程序,等f1代码执行完成,就resolve我们的promise,然后去调用回调函数f2。

6.Generator函数

function* helloWorldGenerator(){
yield ‘hello’;
yield ‘world’;
return ‘ending’;
}
var hw = helloWorldGenerator();
image.png

7.async和await

https://es6.ruanyifeng.com/#docs/async
async 表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
在没有await的情况下执行async函数,它会立即执行,返回一个Promise对象,并且,绝不会阻塞后面的语句
async函数对 Generator 函数的改进,体现在以下四点。
1)内置执行器。
2)更好的语义。
3)更广的适用性。
4)返回值是 Promise。
进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

8.处理数据方法

slice\splice\push\pop\unshift等

9.闭包

你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数,因为ES6有了块级作用域的概念)。

优缺点
  • 优点
    1.可以读取函数内部的变量
    2.可以让这些局部变量保存在内存中,实现变量数据共享。
  • 缺点
    1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
    2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    10.js继承的6种方式

    一、原型链继承
    二、借用构造函数继承
    三、组合继承(组合原型链继承和借用构造函数继承)(常用)
    四、原型式继承
    五、寄生式继承
    六、寄生组合式继承(常用)

    11.v-if和v-for一起使用的弊端以及解决办法

    v-for的优先级比v-if高,导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
    解决办法:
    1.在v-for的外层包裹一个标签来使用v-if
    2将需要的判断在computed里处理,然后在放到v-for里

Version:0.9 StartHTML:0000000105 EndHTML:0000002028 StartFragment:0000000141 EndFragment:0000001988

12.原生 ajax 的实现步骤;

var Xhr = new XMLHttpRequest()
Xhr.open(“get”,”/api”,false);
Xhr.onreadystatechange = function(){
If(Xhr.readystate == 4){
If(Xhr.status == 200){
Alert(1111)
}
}
}
Xhr.send();
1,创建 ajax 实例
2 执行 open 确定要访问的连接,以及使用哪种方式;
3,监听请求状态;
4,发送 请求

13.instanceof 的原理是什么?

其原理就是测试构造函数的 prototype 是否出现在被检测对象的原型链上。
判断实例对象的proto(隐式原型属性)和构造函数的原型(prototype)是否指向同一个地址

14.axios 拦截器配置

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response; }, function (error) {
// 对响应错误做点什么
return Promise.reject(error); });

15.require 和 import 的区别

1, import 是 es6 语法,require 是 commoJs 语法
2, import 是解构过程,require 是赋值过程;3, import 是编译时确认模块的依赖,require 是运行时加载整个模块,生成一个对象;

17.es6解构

为什么用解构?方便提取数据
1.对象解构
通过key
2.数组解构
通过位置
3.混合解构
对象与数组解构能被用到一起。
4.参数解构
参数结构提供了更清晰地标明函数期望输入的替代方案。它使用对象或数组的模式替代了具名参数。
1:结构的参数是必须的,否则会报错
2:参数结构也可以设置默认值

18.说说es5继承和es6继承

19.事件循环


20.垃圾回收gc

Javascript采用标记-清除为主(高版本浏览器),引用计数为辅的策略(低版本IE)
1. 标记清除
工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:
1. 垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
2. 去掉环境中的变量以及被环境中的变量引用的变量的标记。
3. 再被加上标记的会被视为准备删除的变量。
4. 垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

  1. 引用计数
    工作原理:跟踪记录每个值被引用的次数。

工作流程:
1. 声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。
2. 同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1.
3. 当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1.
4. 当引用次数变成0时,说明没办法访问这个值了。
5. 当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。


22.浏览器线程

image.png

23.宏任务和微任务

https://www.jianshu.com/p/bfc3e319a96b

image.png

24.箭头函数与普通函数的区别?箭头函数this是被申明的时候就作用了

一.外形不同:箭头函数使用箭头定义,普通函数中没有
二.箭头函数都是匿名函数
三.箭头函数不能用于构造函数,不能使用new
四.箭头函数中this的指向不同
在普通函数中,this总是指向调用它的对象,如果用作构造函数,this指向创建的对象实例。
1.箭头函数本身不创建this
也可以说箭头函数本身没有this,但是它在声明时可以捕获其所在上下文的this供自己使用。
注意:this一旦被捕获,就不再发生变化
总结
(1).箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
(2).普通函数的this指向调用它的那个对象

25.for…of 和 for…in区别?

for…of 用于遍历一个迭代器,如数组
for…in遍历对象

  1. for of不能遍历对象
  2. for in 和for of 遍历输出的结果不同

for in 输出为下标
for of为数组的值
3.for in 会遍历自定义属性,for of不会

为什么for…in可以遍历对象而不遍历数组?

for…in会遍历出原型上的所有方法

26.map filter find forEach 之间的区别

map与foreach区别:
.forEach和map的相同点
1.都是数组的方法+都是用来遍历数组
2.两个函数都有4个参数:匿名函数中可传3个参数item(当前项),index(当前项的索引),arr(原数组),还有一个可选参数this
3.匿名函数中的this默认是指向window的
4.对空数组不会调用回调函数
5.不会改变原数组(某些情况下可改变)

map有返回值,forEach没有,map会生成一个新数组,而forEach地址不会变;
fitter 用于过滤,返回结果为真的时候,输出,会把所有匹配的全部过滤出来;
find 用于查找,返回为真的时候,立马输出,找到一个就返回;

27.如何实现三个接口同时成功返回?如果一个失败了怎么办?

promise.all()

vue 问题

vue有哪些优缺点?

vue两大特点:响应式编程组件化
vue的优势:轻量级框架、简单易学、双向数据绑定组件化、数据和结构的分离、虚拟DOM、运行速度快。
vue是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和dom,这样大大加快了访问速度和提升用户体验。而且他的第三方ui库很多节省开发时间。
vue的缺点
1、Vue 不缺入门教程,可是很缺乏高阶教程与文档。同样的还有书籍。
2、VUE不支持IE8
3、生态环境差不如angular和react
4、社区不大

vue组件化的优点

  • 提高开发效率 方便重复使用 简化调试步骤 提升项目的可维护性 便于多人协同开发

    react与vue有什么不同

    相似:
    都是jsUI框架;
    都使用了一种叫’Virtual DOM’的东西;
    都鼓励组件化应用,都是数据驱动视图;
    都有’props’的概念;
    都有自己的构建工具,你可以使用它快速搭建开发环境;
    区别:
  • 组件化的区别
    • Vue本质是MVVM框架,由MVC发展而来;
    • React是前端组件化框架,由后端组件化发展而来;
  • 状态管理(state) vs 对象属性(在Vue中,state对象并不是必须的,数据由data属性在Vue对象中进行管理)
  • Vue使用模板,React使用JSX

    vue3.0新特性

    https://blog.csdn.net/qq_27318177/article/details/119170748
    引入了Tree-Shaking
    生命周期函数新增了一个setup生命周期函数,setup执行的时机是在beforeCreate生命函数之前执行,因此在这个函数中是不能通过this来获取实例的;
    同时为了命名的统一,将beforeDestroy改名为beforeUnmount,destroyed改名为unmounted
    新增的功能:响应式API、响应式侦听(vue3也提供了两个函数来侦听数据源的变化:watch和watchEffect。)、组合API等

    深入了解vue

    vue是一个构建数据驱动的web界面的渐进式MVVM框架,性能好、简单易用、前后端分离、单页面应用用户体验好
    vue常见的指令 :v-html、v-if、v-show、v-for、v-model、v-once、v-on
    vue.js的两个核心是数据驱动、组件系统

    MVVM响应式原理

    vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。
    通过Object.defineProperty()来劫持对象属性的setter和getter操作,在数据变动时做你想要做的事情。
    https://www.cnblogs.com/zhouyideboke/p/9626804.html 链接
    1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
    2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
    3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并初始化模板数据以及初始化相应的订阅器。
    4.VUE语法糖: this.$emit(‘input’, 123)

image.png

vue生命周期

创建-》挂载-》更新-》卸载

  • beforeCreate阶段:vue实例的挂载元素el和数据对象data都是undefined,还没有初始化。
  • created阶段:vue实例的数据对象data有了,可以访问里面的数据和方法,未挂载到DOM,el还没有
  • beforeMount阶段:vue实例的el和data都初始化了,但是挂载之前为虚拟的dom节点
  • mounted阶段:vue实例挂载到真实DOM上,就可以通过DOM获取DOM节点
  • beforeUpdate阶段:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
  • updated阶段:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数据,防止死循环
  • beforeDestroy阶段:实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件
  • destroyed阶段:实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁

    vue中父组件能监听到子组件的生命周期吗

    能,通过@hook:进行监听代码如下:
    // 这里是父组件
    <template>
    <child
    @hook:mounted="getChildMounted"
    />
    </template>
    <script>
    method: {
    getChildMounted () { // 这里可以获取到子组件mounted的信息
    }
    }
    </script>

说一下v-model内部原理?如何自己实现一个v-model?如何在你实现的v-model里面修改数据?

v-model很好用,我们经常用它做双向绑定;
v-model其实是个语法糖,它实际上是做了两步动作:
1、绑定数据value
2、触发输入事件input

<template>
<div id="app"> {{username}} <br/>
<input type="text" :value="username" @input="username=$event.target.value">
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
username:''
}
}
}
</script>

自己实现v-model代码:

model 接受有两个属性:(相当于重命名)

  • props 代替原来 val 的值。
  • event 代替原本 input 出发的事件


如何在你实现的v-model里面修改数据?
直接使用changeStatus事件来修改数据

vue组件传值

父传子、子传父、非父子组件传值
1、父组件向子组件进行传值
props
2.子传父
$emit
3.非父子组件进行传值
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果
bus运用,beforeDestroy销毁,Bus.$off

祖先和后代之间通信:provide/inject
跨级通信还可以使用 vuex;

子组件修改父组件数据方法有哪些?

1.通过$emit的方法给父组件进行传值,那么我们在传值的时候对父组件的数据进行更改,就完成了对父组件的数据更改;
2.通过.sync修饰符和update来更改数据,该修饰符的意思就是允许子组件自行更改数据

方法总结:
  1. 子组件通过$emit方法调用update属性
  2. 子组件直接对值进行更改并更新

vue中父组件如何获取子组件的属性和方法

在子组件上定义ref属性来获取子组件的属性和方法
// 这里是父组件
<templete>
<child ref="child"/>
</templete>
<script>
method: {
getChild () {
this.$refs.child.属性名(方法名)
}
}
</script>

组件 data 为什么返回一个函数

组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新
的 data,如果单纯写成对象形式,就使得所有组件实例共用了一份 data,造成了数据污染

说一下虚拟dom?

简单来说,可以把Virtual DOM 理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性。不同的框架对这三个属性的命名会有点差别。

模板 → 渲染函数 → 虚拟DOM树 → 真实DOM的一个过程

image.png
其实虚拟DOM在Vue.js主要做了两件事:

提供与真实DOM节点所对应的虚拟节点vnode
将虚拟节点vnode和旧虚拟节点oldVnode进行对比(diff算法),然后更新视图

总结:「vdom是为了减轻性能压力。dom是昂贵的,昂贵的一方面在dom本身的重量,dom节点在js里的描述是个非常复杂属性很多原型很长的超级对象,另一方面是浏览器渲染进程和js进程是独立分离的,操作dom时的通信和浏览器本身需要重绘的时耗都是很高的。所以大家机智的搞了个轻量的vdom去模拟dom,vdom每个节点都只挂载js操作的必要属性,每次组件update时都先操作vdom,通过vdom的比对,得到一个真实dom的需要操作的集合。整个机制是在JavaScript层面计算,在完成之前并不会操作DOM,等数据稳定之后再实现精准的修改。」

为什么虚拟 dom 会提高性能?

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。

然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

虚拟 Dom,Diff 算法的原理

如果元素类型发生变化,直接替换
如果是文本则比较文本里面的内容是否有差异,
如果是元素就需要比较当前元素的属性是否相等,会先比较 key;

diff算法

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁。
image.png

以前的diff与现在vue的diff有什么区别,在哪些方面做了优化?

传统diff算法通过循环递归对节点进行依次对比效率低下;
现在的React、Vue则是放弃了完全比对及最小修改;
优化措施有:

  • 「分层diff」:不考虑跨层级移动节点,让新旧两个VDOM树的比对无需循环递归(复杂度大幅优化,直接下降一个数量级的首要条件)。这个前提也是Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。

在同层节点中,采用了「双端比较的算法」过程可以概括为:oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一个已经遍历完了,就会结束比较;
image.png
当发生以下情况则跳过比对,变为插入或删除操作:

  • 「组件的Type(Tagname)不一致」,原因是绝大多数情况拥有相同type的两个组件将会生成相似的树形结构,拥有不同type的两个组件将会生成不同的树形结构,所以type不一致可以放弃继续比对。

  • 「列表组件的Key不一致」,旧树中无新Key或反之。毕竟key是元素的身份id,能直接对应上是否是同一个节点。

  • 对触发了getter/setter 的组件进行diff,精准减少diff范围

vue的diff是同级比较吗?是

key的作用

key来给每个节点做一个唯一标识,作用是为了高效的更新虚拟DOM

vue中的事件修饰符主要有哪些?分别是什么作用?

.stop: 阻止事件冒泡
.native: 绑定原生事件
.once: 事件只执行一次
.self:将事件绑定在自身身上,相当于阻止事件冒泡
.prevent: 阻止默认事件
.caption: 用于事件捕获

nexttick原理

nextTick定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
简单理解就是:当数据更新了,在dom中渲染后,自动执行该函数
在 created 和 mounted 阶段,如果需要操作渲染后的试图,也要使用 nextTick 方法。

nexttick原理?为什么能知道dom渲染完成了?

vuex

https://blog.csdn.net/weixin_44667072/article/details/101164766

理解vuex

Vuex采用MVC模式中的Model层,规定所有的数据必须通过action—>mutaion—>state这个流程进行来改变状态的。再结合Vue的数据视图双向绑定实现页面的更新。统一页面状态管理,可以让复杂的组件交互变的简单清晰,同时在调试时也可以通过DEVtools去查看状态。

在当前前端的spa模块化项目中不可避免的是某些变量需要在全局范围内引用,此时父子组件的传值,子父组件间的传值,兄弟组件间的传值成了我们需要解决的问题。虽然vue中提供了props(父传子)commit(子传父)兄弟间也可以用localstorage和sessionstorage。但是这种方式在项目开发中带来的问题比他解决的问题(难管理,难维护,代码复杂,安全性低)更多。vuex的诞生也是为了解决这些问题,从而大大提高我们vue项目的开发效率。

交互方式

Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用 commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新。
image.png

vuex实现

const store = new Vuex.Store({
state: {
count: 0
},

//state的值只能通过mutations来修改
mutations: {
increment(state) {
state.count++
}
},

//this.$store.commit(“increment”)触发mutations中函数”increment”
actions: {
increment({commit}) {
commit(“increment”); //this.$store.commit(“increment”)
}

},

//通过getter中的方法来获取state值
getters: {
getCount(state) {
return state.count
}
}
})

export default store

vuex的数据刷新之后还在吗,怎么做持久化?

不在

怎么做数据持久化

https://www.jianshu.com/p/ffc0e36ea50d
1.补充本地存储 localStorage
2.插件vuex-persistedstate
原理:刷新页面的一瞬间,vuex数据消失,vuex回去sessionStorage中哪会数据,变相的实现了数据刷新不丢失~
npm install vuex-persistedstate —save

引入及配置

在store下的index.js中
image.png

vue-route

  • vue-router是怎么传递参数的
    (1)通过在router.js文件中配置path的地方动态传递参数 eg: path: ‘/detail/:id’
    (2).在router-link标签中传递参数

params: {
x: 1}}
/>
获取:this.$route.params.id

this.$route.query和this.$route.params两种传参方式的区别

**一、this.$route.query的使用


1.传参数**
this.$router.push({ path: ‘/trading’, query:{ id:id, } })

2.获取参数( query相对应的是path params相对应的是name )
this.$route.query.id

3.url的表现形式(url中带有参数)
http://localhost:8090/#/trading?id=1
PS: 页面之间用路由跳转传参时,刷新跳转后传参的页面,数据还会显示存在

**二、this.$route.params的使用


1.传参数**
this.$router.push({ name: ‘trading’, params:{ id:id, } })

2.获取参数
this.$route.params.id

3.url的表现形式(url中不带参数)
http://localhost:8090/#/trading
PS: 页面之间用路由跳转传参时,刷新跳转后传参的页面,数据不存在

彩蛋:this.$route.query的使用方法二
(直接拼接形式)
1.传参:
问题整理 - 图10

2.接收参数:
问题整理 - 图11

vue- route的钩子函数


首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
beforeEach主要有3个参数to,from,next:
to: route即将进入的目标路由对象
from: route当前导航正要离开的路由
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

gitlab版本控制

v-loader是什么

vue文件的一个加载器,将template/js/style转换成js模块
用途: js可以写es6、style样式可以scss、less、template可以加jade等

防抖和节流

防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
例如:用在输入框的时候,假设一秒之内连续输入,只执行最后一次输入
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。
例如:用在监听滚动事件的时候,连续滚动,就隔一段时间执行一次

webpack

webpack 是基于入口的,会自动递归解析入口所需要加载的所有资源,然后用不同的 loader 来处理不 同的资源,用 plugin 来扩展功能;

webpack有自己配制过吗,配置了那些项

image.png

webpack 的构建流程

1, 初始化参数,从配置文件和 shell 语句中读取与合并参数,得出最终的参数;
2, 开始编译,用上一步得到的参数初始化 compiler 对象,加载所有配置的插件,执行对象的 run
方法开始编译
3, 确定入口,根据配制中的 entry 找到所有的入口文件;
4, 编译模块,从入口文件出发,调用所有配置的 loader 对模块进行翻译,再找出该模块依赖的模

5, 完成编译模块,所有的 loader 翻译完所有模块后,得到每个模块被翻译后的最终内容和他们之
间的依赖关系
6, 输出资源,根据入口和模块之间的依赖,组成一个个包含多个模块的 chunk,再把每个 chunk
转换成一个单独的文件加入到输出列表
7, 输出完成,在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入文件系


如何利用 webpack 优化前端性能

1, 压缩代码,删除多余的代码,可以利用 webpack 的 uglifysPlugin 和 parallelUglifyPlugin 来压缩 js 文件
2, 利用 cdn 加速,在构建过程中将引用的静态资源路径修改为 cdn 上对应的路径,可利用 webpack 对应的 output 参数和各个 loader 的 publicPath 参数来修改资源路径。
3, 删除死代码(tree shaking),将代码中永远不会走到的片段删除掉,可以在通过启动 webpack 时追加参数—optimize—minimize—来实现
4, 提取公共代码,CommonChunkPlugin

如何提高 webpack 的构建速度

1.在多入口情况下使用 commonChunkPlugin 来提取公共代码
2,使用 Tree Shaking 来删除多余代码
3,利用 webpack-paralell-plugin 来提升 uglifyPlugin 的压缩速度

css

1.flex布局

http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
6个属性设置在容器上。

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

移动端常遇到的一些兼容性问题

1,解决 input 失焦后页面没有回弹
出现条件:页面高度过小,聚焦时页面需要往上移动的时候
解决办法:在聚焦时,获取当前滚动条高度,然后失焦时,赋值之前获取的高度
2,滑动不顺畅,粘手
一般在 ios 设备中,自定义盒子 overflow:auto|scroll 后出现的;
解决方法:div{ -webkit-overflow-scrolling:touch;}
3,滑动穿透挡在遮罩上滑动的时候,是会穿透到父节点的,最简单的办法就是阻止默认行为
在 vue 中


4,忽略自动识别
content=”telephone=no”> content=”email=no”>
Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示, 可通过加入 CSS 属性
-webkit-text-size-adjust: none; 解决

常见 web 安全及防护原理

1.sql 注入原理:是将 sql 代码伪装到输入参数中,传递到服务器解析并执行的一种攻击手法。也就是
说,在一些对 server 端发起的请求参数中植入一些 sql 代码,server 端在执行 sql 操作时,会拼接对应
参数,同时也将一些 sql 注入攻击的“sql”拼接起来,导致会执行一些预期之外的操作。
防范:1.对用户输入进行校验 2.不适用动态拼接 sql
2.XSS(跨站脚本攻击):往 web 页面插入恶意的 html 标签或者 js 代码。
举例子:在论坛放置一个看是安全的链接,窃取 cookie 中的用户信息
防范:1.尽量采用 post 而不使用 get 提交表单 2.避免 cookie 中泄漏用户的隐式
3.CSRF(跨站请求伪装):通过伪装来自受信任用户的请求
举例子:黄轶老师的 webapp 音乐请求数据就是利用 CSRF 跨站请求伪装来获取 QQ 音乐的数据
防范:在客服端页面增加伪随机数,通过验证码
XSS 和 CSRF 的区别:
1.XSS 是获取信息,不需要提前知道其他用户页面的代码和数据包
2.CSRF 代替用户完成指定的动作,需要知道其他页面的代码和数据包

http

一次完整http请求过程

域名解析 —> 发起TCP的3次握手 —> 建立TCP连接后发起http请求 —> 服务器响应http请求,浏览器得到html代码 —> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) —> 浏览器对页面进行渲染呈现给用户

输入 url 到页面呈现发生了什么?

1,浏览器的地址栏输入 url 按下回车,浏览器查找当前 url 是否存在缓存,并比较缓存是否过期;
2,dns 解析 url 对应的 ip;
3,根据 ip 建立 tcp 连接(三次握手)
4,http 发送请求;
5,服务器处理请求,浏览器接收 http 响应;
6,渲染页面,构建 dom 树,生成相应的页面出来
http 的请求报文结构是:请求行 请求头 空行 请求体;
tcp 的连接需要三次握手,只要没收到确认消息就要重新发
1),主机向服务器发送一个建立连接的请求
2),服务器接收到请求后发送同意连接的信号;
3),主机接到同意连接的信号后,再次向服务器发送确认信号,自此主机与服务器两者建立了连接

http和https的区别

HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全

http状态码

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误
状态码 状态码英文名称 中文描述
304 Not Modified 如果客户端发送了一个带条件的GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应回这个304状态码。简单的表达就是:服务端已经执行了GET,但文件未变化。
400 Bad Request 客户端请求的语法错误,服务器无法理解(错误请求)
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求(禁止)
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置”您所请求的资源无法找到”的个性页面(未找到)
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式(不支持媒体类型)
500 Internal Server Error 服务器内部错误,无法完成请求