最新面试题整理(1)

js原生

map和foreach的区别 **

2.2.1、forEach()返回值是undefined,不可以链式调用。
  2.2.2、map()返回一个新数组,原数组不会改变。
  2.2.3、没有办法终止或者跳出forEach()循环,除非抛出异常,所以想执行一个数组是否满足什么条件,返回布尔值,可以用一般的for循环实现,或者用Array.every()或者Array.some();
  2.2.4、$.each()方法规定为每个匹配元素规定运行的函数,可以返回 false 可用于及早停止循环。
https://www.jianshu.com/p/83aa9a2a40550

5、解释下JavaScript中this是如何工作的。 ****

this永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。匿名函数或不处于任何对象中的函数指向window 。
1.如果是call,apply,with,指定的this是谁,就是谁。
2.普通的函数调用,函数被谁调用,this就是谁。

异步线程,轮询机制,宏任务微任务 ****

https://blog.csdn.net/u013362969/article/details/89714436
https://www.cnblogs.com/ckAng/p/11133643.html
https://zhuanlan.zhihu.com/p/33058983

阻止冒泡 **

w3c方法是ev.stopPropagation()
IE中方法是window.event.cancelBubble = true

阻止默认事件 **

ev.preventDefault()
return false;//写在函数的最后一句

02.怎样判断array 和 object ***

https://www.jianshu.com/p/898d860497ed

-01 数据类型的隐式转换 **

https://www.jianshu.com/p/7cb41d109b7e

01 Div里面有一个div *****

1、有几种方法可以水平,垂直居中 https://www.cnblogs.com/a-cat/p/9019184.html
回答完后会继续问
2、当里面div的框高不固定时,怎么水平垂直居中 https://www.jb51.net/css/56268.html

说一说盒子模型 ****

布局的时候使用的,div ,div的 margin padding border
普通盒模型、怪异盒模型的区别
ie 和其他浏览器对盒模型的 margin 和 padding的解析有区别

11 算法,一个数组【000000000111111111111】这样,你怎么找出第一个1,最底层的js原生写法, 列如第一个数与第二个数作比较,当第二个大于第一个元素的时候就找出了第一个1,那还有没有更效率的写法

使用循环或递归来实现

12 对象的key能使数字吗? *

可以是数字,object对应的key没有限制,只是如果是数字,取值的时候就不能用英文句号(.),只能用[]的方式取值。

1. async await 和promise和generator有什么区别 ****

这几种都可以解决异步操作的地狱回调问题
async await 和promise对象的区别:
async和promise都是异步方法,区别是async生成的结果是promise对象,async是promise的终结版。
await只能在async中使用,await是阻塞的意思,就是暂停,你一起调用2个接口,第一个执行完,不输出结果,要等最第二个接口执行完,才返回这两个的结果。
是属于将异步操作转化为同步操作的做法

async await和generator:
async是Generator的语法糖 ,也就是说,async是对generator的实现,而generator代码更复杂。
generator 除了能解决回调地域问题,还可以作为迭代器使用。generator 语法一般用于redux-saga
redux-saga 一般在umi或dva框架中使用

2.手写promise ***

new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve(‘成功’) // 数据处理完成
// reject(‘失败’) // 数据处理出错
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
/******************/
const promiseClick =()=>{
console.log(‘点击方法被调用’)
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log(‘执行完成Promise’);
resolve(‘要返回的数据可以任何数据例如接口返回数据’);
}, 2000);
});
return p
}
promiseClick().then(()=>{
//成功的回调
},()=>{
//失败的回调
});

new Promise(function(resolve,reject){
//返回resolve还是reject
}).then(function(){
//接收的成功回调
},function(){
//接收失败回调
})

3.promise.all作用 ***

Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或
参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),
失败的原因是第一个失败 promise 的结果。
它通常在启动多个异步任务并发运行并为其结果创建承诺之后使用,以便人们可以等待所有任务完成。
通俗的说法:解决promise的同步调用问题,可以将多个异步操作转为同步操作,缺点:只要有一个promise返回错误,那么后面的promise都不会再执行

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});

promise.allsettled

4.什么是工厂模式,有什么优缺点 *

工厂模式是一种设计模式,目的是为了创建对象,它通常在类或类的静态方法中实现,
有以下目的:当创建相似对象是执行重复操作
当编译时,不知道具体类型的情况下,为工厂客户提供一个创建对象的接口

//使用工厂方式创建一个对象
			function createPerson(name,sex){
				//1.原料
				var obj = new Object();
				//2.加工  -- 对属性进行赋值
				obj.name = name;
				obj.sex = sex;
				//3.方法
				obj.showName = function(){
					console.log("人物名称:"+this.name);
				}
				obj.showSex = function(){
					console.log("人物的性别:"+this.sex);
				}
				//4.加工结束,--输出返回
				return obj;	
			}
			//工厂模式的使用
			var person1 = createPerson("如花","男");
			//调用工厂里的方法
			person1.showName();
			person1.showSex();
			var person2 = createPerson("凤姐","女");
			//调用工厂里的方法
			person2.showName();
			person2.showSex();
			/*
			工厂模式:
			优点: 写好了工厂方法后,只要原料足够,我们可以无限次的创建新的对象
			缺点: 1.没有使用 new ,2.每个对象都有自己的函数,浪费资源

接触过哪些设计模式: 工厂模式 、单例模式(数据库连接)、观察者模式(双向绑定原理)、订阅模式、mvc模式、mvvm模式

5.图片/文件夹上传到后台是什么类型? *

图片上传后台有三种格式:

  1. file格式 (创建formData来完成file上传)
 var formData = new FormData();
                    $.each($(‘#imgfile‘)[0].files, function (i, file) {
                        formData.set(‘idcard‘, file);   //idcard  字段 根据自己后端接口定
                    });
                    //processData: false, contentType: false,多用来处理异步上传二进制文件。
                    that.$indicator.open();
                    $.ajax({
                        url: ‘http://wjtest.jecinfo.cn:9090/indentity/check‘,
                        type: ‘POST‘,
                        data: formData,                    // 上传formdata封装的数据
                       ....
                        }
  1. base64格式
<input type="file" id="imgfile">
var base64Pic = ‘‘
document.getElementById(‘imgfile‘).onchange = function(){
      var fileReader = new FileReader();
      fileReader.readAsDataURL(this.files[0]);
      fileReader.onload = function(){
          base64Pic = fileReader.result;
          console.log(base64Pic )  //base64   可以直接放在src上 预览
      }

3.Blob流格式

6.原生基础数据类型和引用数据类型的区别 *

1.栈(stack)和堆(heap)stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小也不一定会自动释放。
2.基本的数据类型:String, Number, boolean, Null, Undefined,Symbol(ES6新增)  *****
  特点: 存储的是该对象的实际数据,(存放在栈中)
3.对象数据类型(也称为引用数据类型):Array,Object,Function
  特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里,(存放在堆内存中的对象,每个空间大小不一样,要根据情况进行特定的配置)
注:在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象

7.深浅拷贝: ****

1、区别: 浅拷贝/深度拷贝
判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用
知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用

2、常用的拷贝技术
for循环完成深拷贝
二、深拷贝
1、js数组的slice方法
var arr1 = [“前端”,“安卓”,“苹果”];
var arr2 = arr1.slice(0);
arr2[0] = “后端”;
console.log(“原始值:” + arr1 );//前端,安卓,苹果
console.log(“新值:” + arr2);//后端,安卓,苹果
理解:通过JS的slice方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响。
缺点:适用于对不包含引用对象的一维数组的深拷贝
2、js数组的concat方法
var arr1 = [“前端”,“安卓”,“苹果”];
var arr2 = arr1.concat();
arr2[0] = “后端”;
console.log(“原始值:” + arr1 );//前端,安卓,苹果
console.log(“新值:” + arr2);//后端,安卓,苹果
理解:concat方法,原数组和新数组修改某值后,不会改变。
缺点:适用于对不包含引用对象的一维数组的深拷贝

1). arr.concat(): 数组深拷贝
  2). arr.slice(): 数组深拷贝
  3).Object.assign()对象深拷贝
  4). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据
  5). 浅拷贝包含函数数据的对象/数组
  6). 深拷贝包含函数数据的对象/数组
对于多层对象和数组:可以使用 递归调用、JSON.parse(JSON.stringify(arr/obj))、jquery的extend方法来实现深拷贝

https://blog.csdn.net/xuexizhe88/article/details/80990529
https://www.cnblogs.com/echolun/p/7889848.html

8.弹性布局。浮动布局 table布局 *****

弹性布局:使用 百分比、rem 、flex 自适应布局
浮动布局:使用 float clear
table布局:一般用于后台显示
自适应布局和响应式布局:一般需要用到media媒体查询完成,需要根据屏幕宽度的不同,写多个css样式文件

9.flex 的水平居中和垂直居中 ****

水平:justify-content:center; 垂直:align-content:center;
flex:1 的值是1 1 0%,【父控件有剩余空间占1份放大,父控件空间不足按1缩小,自身的空间大小是0%】 ***
flex属性 是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
推荐使用此简写属性,而不是单独写这三个属性。
flex-grow:定义项目的的放大比例;
默认为0,即 即使存在剩余空间,也不会放大;
所有项目的flex-grow为1:等分剩余空间(自动放大占位);
flex-grow为n的项目,占据的空间(放大的比例)是flex-grow为1的n倍。
flex-shrink:定义项目的缩小比例;
默认为1,即 如果空间不足,该项目将缩小;
所有项目的flex-shrink为1:当空间不足时,缩小的比例相同;
flex-shrink为0:空间不足时,该项目不会缩小;
flex-shrink为n的项目,空间不足时缩小的比例是flex-shrink为1的n倍。
flex-basis: 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间,
默认值为auto,即 项目原本大小;
设置后项目将占据固定空间。
所以flex属性的默认值为:0 1 auto (不放大会缩小)
flex为none:0 0 auto (不放大也不缩小)
flex为auto:1 1 auto (放大且缩小)

10.闭包 *****

闭包定义:闭包就是能够读取其他函数内部变量的函数。
闭包可以就解决全局作用域污染的问题
闭包使用场景,闭包的应用场景:
1.setTimeout
  原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。

 function f1(a) {
     function f2() {
         console.log(a);
     }
     return f2;
 }
 var fun = f1(1);
 setTimeout(fun,1000);//一秒之后打印出1

2.回调
  定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。

   <a href="#" id="size-12">12</a>
     <script type="text/javascript">
         function changeSize(size){
             return function(){
                 document.body.style.fontSize = size + 'px';
             };
         }
         var size12 = changeSize(12);
         document.getElementById('size-12').onclick = size12;
     </script>

3.函数防抖 ***
  在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
   实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。

 // fn [function] 需要防抖的函数
 // delay [number] 毫秒,防抖期限值
 
 function debounce(fn,delay){
     let timer = null
     //借助闭包
     return function() {
         if(timer){
             clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
             timer = setTimeOut(fn,delay) 
         }else{
             timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
         }
     }
 }

4.封装私有变量
  如下面代码:用js创建一个计数器

 function f1() {
     var sum = 0;
     var obj = {
        inc:function () {
            sum++;
            return sum;
        }
 };
     return obj;
 }
 let result = f1();
 console.log(result.inc());//1
 console.log(result.inc());//2
 console.log(result.inc());//3

所有js数据类型都拥有valueOf和toString这两个方法,null除外valueOf()方法:返回指定对象的原始值。
toString()方法:返回对象的字符串表示。在数值运算中,优先调用了valueOf,字符串运算中,优先调用toString. sum+’ '是一个字符串类型的数据

 function f1() {
     var sum = 0;
     var obj = {
        inc:function () {
            sum++;
            return sum;
        }
 };
     return obj;
 }
 let result = f1();
 console.log(result.inc());//1
 console.log(result.inc());//2
 console.log(result.inc());//3

闭包产生问题:容易产生内存泄漏 (原因:闭包使用时,扩展了他变量的原有作用域,使变量常驻内存)
内部函数 被 外部函数 包含时,内部函数会将外部函数的局部活动对象添加到自己的作用域链中。

 outerFun(outerArgument){
     //被包含的内部函数可以访问外部函数的变量
     return function(){  
         return outerArgument+1
     } 
 } 

而由于内部匿名函数的作用域链 在引用 外部包含函数的活动对象 ,即使outFun执行完毕了,它的活动对象还是不会被销毁!
即,outerFun的执行环境作用域链都销毁了,它的活动对象还在内存中留着呢。
并且根据垃圾回收机制,被另一个作用域引用的变量不会被回收。
所以,除非内部的匿名函数解除对活动变量的引用(解除对匿名函数的引用),才可以释放内存。

 // 创建函数 还未调用
 var creatFun = outerFun(7)
 // 调用函数
 var result = creatFun(8)
 // 解除对匿名函数的引用
 creatFun = null

所以,闭包会造成内存泄漏,就是因为它把外部的包含它的函数的活动对象也包含在自己的作用域链中了,会比一般的函数占用更多内存。
怎样解决:在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;

 window.onload = function(){
         var el = document.getElementById("id");
         el.onclick = function(){
             alert(el.id);
         }
     }
     解决方法为
     window.onload = function(){
         var el = document.getElementById("id");
         var id = el.id;                                      //解除循环引用
         el.onclick = function(){
             alert(id); 
         }
         el = null;                                          // 将闭包引用的外部函数中活动对象清除
     }

循环使用闭包会有什么问题:在循环中使用闭包容易产生每个 i都有自己的独立作用于,导致输出结果都是循环的最后的值这种问题

 //循环里面包含闭包函数
 function box(){
     var arr = [];
     for(var i=0;i<5;i++){
         arr[i] = function(){
             return i;                            //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
         }                                        //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
     }                                            //当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5
     return arr;
 }
 //alert(box());                                    //执行5次匿名函数本身
 //alert(box()[1]);                   //执行第2个匿名函数本身
 //alert(box().length);                            //最终返回的是一个数组,数组的长度为5
 alert(box()[0]());  

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,
而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,所以这个box得到的是一个数组[5,5,5,5,5]。
解决方法:

 function box(){
     var arr = [];
     for(var i=0;i<5;i++){
         arr[i] = (function(num){                    //自我执行,并传参(将匿名函数形成一个表达式)(传递一个参数)
             return num;                            //这里的num写什么都可以                    
         })(i);                                    //这时候这个括号里面的i和上面arr[i]的值是一样的都是取自for循环里面的i                            
     }                                            
     return arr;
 }
 //alert(box());                                
 //alert(box()[1]);
 //alert(box().length);                            
 alert(box()[0]);  

11.什么是内存泄漏,都什么情况容易产生内存泄漏 **

内存泄漏:即为变量内容持续占用内存空间,不释放,垃圾回收机制也没有将该内存回收的情况
死循环
定时器没有清除
绑定的事件没有解除
递归调用没有结束条件

主要存在内存泄漏的问题点
BOM DOM对象泄漏
scipt中存在对BOM DOM对象的引用
javaScript对象泄漏
闭包函数导致的泄漏
3、主要关注的代码点
DOM中的addEventLisner 函数及派生的事件监听, 比如Jquery 中的on 函数, vue 组件实例的 $on 函数,第三方库中的初始化函数
BOM对象的事件监听,比如webSocket的监听事件
避免不必要的函数引用
如果是要render函数,避免在html标签中DOM BOM事件

12.原型 ,原型链,继承的方式 *****

原型:既构造函数的prototype.每个构造函数都有一个prototype属性指向生成这个函数的原型对象,简称原型;
prototype 可以对构造函数进行扩展,既添加构造函数的属性和方法
原型链:每个对象都有一个__proto__属性, 指向生成改对象的原型对象,这样,我们就可以找到是哪个对象生成了改对象,
原型链一般用于继承
原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。
因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,它==null。

 function Person(name){
             this.name = name;
      }
      var p = new Person();
      //p ---> Person.prototype --->Object.prototype---->null
 

原型继承

//原型继承的基本案例
function Person(name, age) {
	this.name = name;
	this.age = age;
}
//1.直接替换原型对象 
var parent = {
	sayHello : function() {
		console.log("方式1:替换原型对象");
	}
}
Person.prototype = parent;
var p = new Person("张三", 50);
p.sayHello();
//2.混入式原型继承
console.log(".............混入式原型继承..............");
function Student(name, age) {
	this.name = name;
	this.age = age;
}
var parent2 = {
	sayHello : function() {
		console.log("方式2:原型继承之混入式加载成员");
	}
}
for ( var k in parent2) {
	Student.prototype[k] = parent2[k];
}
var p = new Student("张三", 50);
p.sayHello();

继承的方式:

13. this指向 ,箭头函数的this指向 ****

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象

15. 使用node.js 创建本地服务器 *

16. Git常用命令 *****

git init 初始化 *****
git clone 克隆代码库 *****
git config 配置
git add 增加文件到暂存区 *****
git commit 提交暂存区到仓库 *****
git branch 名称 新建分支 *****
git checkout 切换分支 *****
git merge 合并分支 *****
git branch -d 删除分支 *****
git tag 打tag 包 *****
git status 查看状态 *****
git log 查看日志 *****
git diff 查看暂存区和工作区差异
git fetch 下载远程仓库的变动 *****
git pull 取回远程仓库变化,并与本地分支合并 *****
git push 上传本地指定分支到远程仓库 *****
解决冲突:

17. 跨域的解决方案 *****

因为前端有同源保护政策,所以,不同源或者说不同的域名和ip之间不能进行访问。

1.jsonp jsonp有什么问题?只能是get方式不能是post方式 jsonp原理:script标签的src属性可以跨域
2.proxy代理 只能是打包前使用,打包后需要后台配置跨域 nginx反向代理
3.后台头部设置 Access-Control-Allow-Origin ,cors
4.其他 方式:
a. document.domain + iframe (只有在主域相同的时候才能使用该方法)
b. location.hash + iframe
c. window.name + iframe
d. postMessage(HTML5中的XMLHttpRequest Level 2中的API)
e. web socket
web sockets是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。

18. for循环定时器打印产生问题,怎么解决 ** js异步轮询机制

for(var i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
}, 1000);
}
打印结果为5个6;
原因是:js是单线程,有任务队列,任务队列分为两种,同步任务和异步任务。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
所以循环是同步任务先执行,当执行完之后,当setTimeout的异步操作准备好后,通知主线程,主线程将其从异步队列中取出来,再执行,所以当循环完成时,i的值位6,setTimeout再执行,打印5个6

所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
事件循环(event loop)
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

19. http协议详解 http请求方式有 http响应状态码 *****

1.http 特点:
1.支持客户/服务器模式。
2.简单快速:。
3.灵活:
4.无连接:
5.无状态:
2. http请求由三部分组成,分别是:请求行、消息报头、请求正文
请求方法(所有方法全为大写)有多种,各个方法的解释如下:
GET 请求获取Request-URI所标识的资源
POST 在Request-URI所标识的资源后附加新的数据
HEAD 请求获取由Request-URI所标识的资源的响应消息报头
PUT 请求服务器存储一个资源,并用Request-URI作为其标识
DELETE 请求服务器删除Request-URI所标识的资源
TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT 保留将来使用
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求

3.在接收和解释请求消息后,服务器返回一个HTTP响应消息。
HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求

301 永久移动,请求的资源被永久的移动到新url,返回信息会包括新的url。浏览器会自动定向到新url
302 临时移动,资源只是临时被移动,客户端赢继续使用原有url
304 未修改,所请求的资源未修改,服务器返回此状态码是=时,不会返回任何资源,客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源

400 Bad Request //客户端请求有语法错误,不能被服务器所理解,解决方法:修改请求的参数及语法
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 ,
解决方式:即没有启用任何认证方式,只需要在IIS Manager里面启用需要的认证方式即可。
即被Authorization Rule阻挡,则需要分析这个authorization rule是否是否必须来决定对他的更改。
403 Forbidden //服务器收到请求,但是拒绝提供服务
  1、你的IP被列入黑名单。
  2、你在一定时间内过多地访问此网站(一般是用采集程序),被防火墙拒绝访问了。
  3、网站域名解析到了空间,但空间未绑定此域名。
  4、你的网页脚本文件在当前目录下没有执行权限。
  6、以http方式访问需要ssl连接的网址。
  7、浏览器不支持SSL 128时访问SSL 128的连接。
  8、在身份验证的过程中输入了错误的密码。
解决方式: 1、重建dns缓存
  对于一些常规的403 forbidden错误,马海祥建议大家首先要尝试的就是重建dns缓存,在运行中输入cmd,然后输入ipconfig /flushdns即可。如果不行的话,就需要在hosts文件里把主页解析一下了。
  2、修改文件夹安全属性
  3、关于apache导致的403 forbidden错误,需设置Apache的配置文件。
  4、关于HawkHost空间出现403 Forbidden错误需设置htaccess文件。
404 Not Found //请求资源不存在,eg:输入了错误的URL 解决办法:输入正确的url地址
405 请求方式不对 ,比如原本需要post方式请求的,你写了get方式请求

20. 一个页面从发送http请求到渲染页面的全过程(http事务流程)***

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

21.tcp和udp的区别 *

TCP与UDP区别总结:
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

##22.什么是长连接 *
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),
每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时
,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个
时间。实现长连接需要客户端和服务端都支持长连接。

23.ajax是同步还是异步,ajax的流程 *****

ajax是异步的,
流程:
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求 .(sned)
(5)获取异步调用返回的数据.(onreadystatechange)
(6)使用JavaScript和DOM实现局部刷新.

24.h5新特性 ***

1.语义化标签

4.Canvas绘图 ***

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");//获取2d作图对象
cxt.moveTo(10,10);//画线的的起始点
cxt.lineTo(150,50);//画线
cxt.lineTo(10,50);
cxt.stroke();//线
cxt.fillStyle="#FF0000";//填充颜色
cxt.beginPath();//开始路径
cxt.arc(70,18,15,0,Math.PI*2,true);//画圆
cxt.closePath();//结束路径
cxt.fill();//填充
cxt.drawImage(img,0,0);//画布填充图片
cxt.createLinearGradient(0,0,175,50); //画布填充渐变

5.SVG绘图
6.地理定位 ***
百度地图引入和使用
7.拖放API ***
draggable=“true”
setData()
drag ondrag 当拖动元素或选中的文本时触发。
dragend ondragend 当拖拽操作结束时触发 (比如松开鼠标按键或敲“Esc”键). (见结束拖拽)
dragenter ondragenter 当拖动元素或选中的文本到一个可释放目标时触发(见 指定释放目标)。
dragexit ondragexit 当元素变得不再是拖动操作的选中目标时触发。
dragleave ondragleave 当拖动元素或选中的文本离开一个可释放目标时触发。
dragover ondragover 当元素或选中的文本被拖到一个可释放目标上时触发(每100毫秒触发一次)。
dragstart ondragstart 当用户开始拖动一个元素或选中的文本时触发(见开始拖动操作)。
drop ondrop 当元素或选中的文本在可释放目标上被释放时触发(见执行释放)。

8.Web Worker
9.Web Storage *****
特性
Cookie 一般由服务器生成,可设置失效时间,(设置过期时间是小于当前时间)。
如果在浏览器端生成Cookie,默认是关闭浏览器后失效;大小 4K左右
每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 需要程序员自己封装,源生的Cookie接口不友好

localStorage 除非被清除,否则永久保存 大小 5M 仅在客户端(即浏览器)中保存,不参与和服务器的通信
源生接口可以接受,亦可再次封装来对Object和Array有更好的支持

sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除 大小 5M 仅在客户端(即浏览器)中保存,不参与和服务器的通信
源生接口可以接受,亦可再次封装来对Object和Array有更好的支持

COOKIE是如何工作的? *

Cookie可用于客户端数据的存储,在没有其它存储办法时,使用这种方式是可行的,但随着现在浏览器开始支持各种各样
的存储方式而逐渐被废弃。 由于服务器指定Cookie以后浏览器的每次请求都会携带Cookie数据,这会带来额外的性能负
担(尤其是在移动环境下)。 新的浏览器API已经允许开发者直接在本地存储数据,如可以使用Web storage API (本地
存储和会话存储)和IndexedDB(索引数据库)。
COOKIE主要用在以下三个方面:
会话状态管理(如用户登录状态、购物车)
个性化设置(如用户自定义设置)
浏览器行为跟踪(如跟踪分析用户行为)

COOKIE的缺陷
每个 HTTP 请求中都包含 Cookies,从而导致传输相同的数据减缓我们的 Web 应用程序。
每个 HTTP 请求中都包含 Cookies,从而导致发送未加密的数据到互联网上,可能会导致数据泄露,虽然进行过加密,但是攻击者拿到cookie后仍然可以登录,因为难以识别是否为同一个用户在登陆。
Cookies 只能存储有限的 4KB 数据,对于复杂的存储需求来说是不够用的。

sessionStroage有哪些应用场景?
答: 在不需要和服务器交互的场所,用来存储用户数据之类的,可以在路由页跳转的时候取出更改储存,减少调用接口的次数,减轻服务器压力。
用storage怎么来判断用户是否需要再登陆?
答:可以用加密的方法存储,每次用户访问的时候可以取出调用服务器接口作为参数发送进行对比,存在账号密码就直接跳过登录页。
localStorage是否可以在同源窗口共享?
答:同一浏览器的相同域名和端口的不同页面间可以共享相同的 localStorage,但是不同页面间无法共享sessionStorage的信息。

10.WebSocket

25.css3新特性 *** 动画效果

css3选择器 https://blog.csdn.net/weixin_42568381/article/details/81738566
border-radius
border-image
background-size
background-origin
background-clip:规定背景的绘制区域。
linear-gradient():线性渐变。
radial-gradient():径向渐变。
word-break:定义如何换行。
word-wrap:允许长的内容可以自动换行。
text-overflow:指定当文本溢出包含它的元素,应该发生什么。
text-shadow:文字阴影。
transform-style:指定嵌套元素是怎样在三维空间中呈现。
2D转换方法
rotate(angle):定义 2D 旋转,在参数中规定角度。
translate(x,y):指定元素在二维空间中的位移。X轴方向向右,Y轴方向向下。
scale(n):定义 2D 缩放转换。
matrix(a,b,c,d,e,f):定义 2D 转换,使用六个值的矩阵。
skew(x-angle,y-angle):定义沿着 X 和 Y 轴的 2D 倾斜转换。
perspective(n):为 3D 转换元素定义透视视图。
translate:指定元素在的位移。
matrix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n):定义 3D 转换,使用 16 个值的 4x4 矩阵。
过渡
transition:设置元素当过渡效果,四个简写属性为: *****
animation:为元素添加动画,是一个简写属性。 *****
css新增的一些伪类
1、p:first-of-type 选择器匹配属于其父元素的特定类型的首个子元素的每个元素。
2、p:last-of-type 选择器匹配属于其父元素的特定类型的最后一个子元素的每个元素。
3、p:only-of-type 选择器匹配属于其父元素的特定类型的唯一子元素的每个元素。
4、p:only-child 选择器匹配属于其父元素的唯一子元素的每个元素。
5、p:nth-child(2) 选择器匹配属于其父元素的第 N 个子元素,不论元素的类型。n 可以是数字、关键词或公式。
6、:enabled :disabled表单控件的禁用状态。
7、:checked:checked 选择器匹配每个选中的输入元素(仅适用于单选按钮或复选框)。
Flex弹性布局 *****
媒体查询 media *

26.es6新特性 *****

let const *****
变量的解构赋值 *****

let [a, b, c] = [1, 2, 3];
let [head, ...tail] = [1, 2, 3, 4];
let { foo, bar } = { foo: "aaa", bar: "bbb" };

字符串扩展

let text='abcdefg';
for (let i of text) {
  console.log(i);
}
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
repeat方法返回一个新字符串,表示将原字符串重复n次。
padStart()用于头部补全,padEnd()用于尾部补全。
模板字符串 `aaa{$test}`

数值的扩展:

Number.isFinite()用来检查一个数值是否为有限的(finite)。
Number.isNaN()用来检查一个值是否为NaN。
Number.parseInt(),转整型
 Number.parseFloat()转浮点型
 Number.isInteger()用来判断一个值是否为整数
 Math.trunc方法用于去除一个数的小数部分,返回整数部分。
 Math.sign方法用来判断一个数到底是正数、负数、还是零。
 Math.cbrt方法用于计算一个数的立方根。
 Math.sign()用来判断一个值的正负,但是如果参数是-0,它会返回-0。
 ES2016 新增了一个指数运算符(**)。

数组的扩展:

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
Array.of方法用于将一组值,转换为数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
fill方法使用给定值,填充一个数组。
entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。该方法属于ES7,但Babel转码器已经支持。

函数的扩展:

函数参数的默认值
与解构赋值默认值结合使用
函数的 length 属性
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真
ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
扩展运算符 ...   *****
替代数组的apply方法 
// ES5的写法
Math.max.apply(null, [14, 3, 77])

// ES6的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

扩展运算符的应用:合并数组 与解构赋值结合 函数的返回值 字符串 实现了Iterator接口的对象 Map和Set结构,Generator函数


/************/
严格模式 'use strict';
重点掌握,重点重点
箭头函数  ES6允许使用“箭头”(=>)定义函数。 箭头函数可以保留this的指向   *****
箭头函数注意点:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。

对象的扩展:

Object.is() 比较两个值是否相等
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
属性的遍历
ES6一共有5种方法可以遍历对象的属性。
(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。
Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象。
Object.keys()引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

set 和 map 数据类型 *****

set可以用于数组去重,是无序的,set中不包含重复的元素
map 的key值可以是数组对象字符串等格式
Map类似于一个对象,是键值对的集合,键值可以是字符串,各种类型,对象。

proxy ***


Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”
var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});

vue双向绑定原理的Object.defineProperty 更改为了 Proxy,性能有所优化

promise *****

解决异步回调地狱问题
var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});


.then() Promise实例添加状态改变时的回调函数。
.catch() 用于指定发生错误时的回调函数。
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
all中的内容是两个异步操作,只有等到它们的结果都返回了,才会触发pickTopRecommentations这个回调函数。
Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。
Promise.resolve()有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
.done()Promise对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到
.finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。

Generator 函数的语法 ***

迭代器或解决异步调用回调地狱
function* gen() {
  yield  123 + 456;
}

redux-saga中使用了该语法

async await *****

解决异步回调地域问题,一般和promise一起使用

class 语法糖 ;解决了js中没有类的概念,需要使用 function做为构造函数来使用的问题,简化了继承 *****

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}

模块module *****

引入模块 import 
输出模块 export 

##28.typescript *
1.基础类型: boolean\number\string\数组\元组(元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同)\枚举(enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字)\ Any\ viod\null\undefined\never(类型表示的是那些永不存在的值的类型)\object
2.变量声明:let const var
3.接口 接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约

interface LabelledValue {  //接口
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

4.类

class Animal {
    move(distanceInMeters: number = 0) {
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}

class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

5.函数

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };

也可以有this和箭头函数

6.泛型可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

function identity<T>(arg: T): T {
    return arg;
}
let output = identity<string>("myString");  // type of output will be 'string'

7.枚举使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。

enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}

8.类型推论 这节介绍TypeScript里的类型推论。即,类型是在哪里如何被推断的。
9.类型兼容性
TypeScript里的类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。 它正好与名义(nominal)类型形成对比。
10.高级类型

交叉类型  交叉类型是将多个类型合并为一个类型

联合类型 联合类型表示一个值可以是几种类型之一。
  1. symbol类型的值是通过Symbol构造函数创建的。
let sym1 = Symbol();

let sym2 = Symbol("key"); // 可选的字符串key

12.迭代器和生成器

for..of迭代的是对象的 键 的列表
for..in则迭代对象的键对应的值

13.模块

export 
import

14.命名空间
随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。 因此,我们把验证器包裹到一个命名空间内,而不是把它们放在全局命名空间下。
15.声明合并

合并接口
interface Box {
    height: number;
    width: number;
}
interface Box {
    scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};
合并命名空间
namespace Animals {
    export class Zebra { }
}

namespace Animals {
    export interface Legged { numberOfLegs: number; }
    export class Dog { }
}

  1. jsx语法
  2. 装饰器
    18.mixins

混入 (mixin) 提供了一种非常灵活的方式,
来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
注意: 对于混入的使用,是将 vue的mixin对象重新拷贝到 组件中;降低性能
数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

是将 vue的mixin对象重新拷贝到 组件中;降低性能 ;vue3.0时会将mixin调优:
Composition API
mixin模式表面上看起来很安全。然而,通过合并对象来共享代码,由于它给代码增加了脆弱性,并且掩盖了推理功能的能力,因此成为一种反模式。
Composition API最聪明的部分是,它允许Vue依靠原生JavaScript中内置的保障措施来共享代码,比如将变量传递给函数和模块系统。
这是否意味着Composition API在各方面都比Vue的经典API优越?不是的。在大多数情况下,你坚持使用经典API是没有问题的。但是,如果你打算重用代码,Composition API无疑是优越的。
链接:https://www.imooc.com/article/303667

19.三斜线指令
20.文件类型检查

##29.队列和栈 *
栈是一种后进先出的数据结构,也就是说最新添加的项最早被移出;它是一种运算受限的线性表,只能在表头/栈顶进行插入和删除操作。
  栈有栈底和栈顶。
  向一个栈插入新元素叫入栈(进栈),就是把新元素放入到栈顶的上面,成为新的栈顶;
  从一个栈删除元素叫出栈,就是把栈顶的元素删除掉,相邻的成为新栈顶;
入栈push 出栈pop

队列是一种先进先出的数据结构。 队列在列表的末端增加项,在首端移除项。
  它允许在表的首端(队列头)进行删除操作,在表的末端(队列尾)进行插入操作;(例如在银行窗口排队办理业务,最前面的第一个人开始办理,后面来的人只能在队伍末尾排队,直到排到他们为止)
  队列是实现多任务的重要机制!
入队列 unshift 出队列 pop

##30. 树组件,遍历树组件 *
https://blog.csdn.net/qq_34295211/article/details/102784498

##31. sass 新特性 **
Sourcemaps
&改善了选择器
改善了if()函数
高级操作列表
新的list-separator()函数
支持Maps
改善了@for循环
@at-root规则
新字符串操作函数
新的@import功能
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/preprocessor/future-sass.html

sass和less区别: *****

  1. sass和less主要区别在于实现方式: less是基于JavaScript的在客户端处理 所以安装的时候用npm,sass是基于ruby所以在服务器处理。
  2. sass与less的安装
    sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby。
    less 在服务器端最容易的安装方式就是通过 npm(node.js 的包管理器)。less 在客户端使用【.less】(LESS源文件),只需要在官网载一个javascript脚本文件主【less.js】,然后在HTML中引入即可。
    3.变量
    sass 是以 开 头 定 义 的 变 量 , 如 : 开头定义的变量,如: mainColor: #963;
    less 是以@开头定义的变量,如 @mainColor: #963;
    4.作用域
    sass 没有全局变量,满足就近原则,但是实际中可以将需要定义的全局属性放在base.scss 文件中。注意变量名重复; less 中的作用域和其他程序语言中的作用域非常的相同,他首先会查找局部定义的变量,如果没有找到,会像冒泡一样,一级一级往下查找,直到根为止。
    区别详细的课参看以下链接:
    https://www.cnblogs.com/tommymarc/p/11627576.html

##32. js排序算法 *
https://www.cnblogs.com/AlbertP/p/10847627.html

##33.网络攻击,及解决办法 *
https://blog.csdn.net/weixin_33781606/article/details/88963588

##34. seo优化 **
1.合理的title、description、keywords
2.语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
3.非装饰性图片必须加alt
4.友情链接,好的友情链接可以快速的提高你的网站权重
5.外链,高质量的外链,会给你的网站提高源源不断的权重提升
6.向各大搜索引擎登陆入口提交尚未收录站点
7.重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,保证重要内容一定会被抓取
8.少用iframe:搜索引擎不会抓取iframe中的内容
9.提高网站速度:网站速度是搜索引擎排序的一个重要指标
##35. 数组去重 ***
https://segmentfault.com/a/1190000016418021

##36. 倒序打印 *
https://blog.csdn.net/qq_42618566/article/details/103187058

##37. css横向居中纵向居中 ****
https://www.cnblogs.com/xiaoxueer/p/11849997.html
https://blog.csdn.net/weixin_37580235/article/details/82317240

38.如何给localStorage设置有效期 **

https://jingyan.baidu.com/article/b2c186c83eef46c46ef6ffbb.html

39.Window. write和document.innerhtml区别 **

主要区别:document.write是直接将内容写入页面的内容流,会导致页面全部重绘,innerHTML将内容写入某个DOM节点,不会导致页面全部重绘
##40.display:none和visibility:hidden的区别是: *
1.display:none是彻底消失,不在文档流中占位,浏览器也不会解析该元素;visibility:hidden是视觉上消失了,可以理解为透明度为0的效果,在文档流中占位,浏览器会解析该元素;
2.使用visibility:hidden比display:none性能上要好,display:none切换显示时visibility,页面产生回流(当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流),而visibility切换是否显示时则不会引起回流。
所以我使用visibility:hidden,在页面渲染时第二个tab页中的轮播图就可以获取宽度做自适应了。

41.doctype的作用: *

1、定义:

标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档。 声明必须是 HTML 文档的第一行,位于 标签之前。

2、作用:
声明文档的解析类型(document.compatMode),避免浏览器的怪异模式。
document.compatMode:
BackCompat:怪异模式,浏览器使用自己的怪异模式解析渲染页面。
CSS1Compat:标准模式,浏览器使用W3C的标准解析渲染页面。
这个属性会被浏览器识别并使用,但是如果你的页面没有DOCTYPE的声明,那么compatMode默认就是BackCompat,
浏览器按照自己的方式解析渲染页面,那么,在不同的浏览器就会显示不同的样式。
如果你的页面添加了那么,那么就等同于开启了标准模式
那么浏览器就得老老实实的按照W3C的标准解析渲染页面,这样一来,你的页面在所有的浏览器里显示的就都是一个样子了。
这就是的作用。

44.常用的数组方法 *****

join():join(separator): 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。
push()和pop():push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。 pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。
shift() 和 unshift():shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。 unshift:将参数添加到原数组开头,并返回数组的长度
sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面
reverse():反转数组项的顺序。
concat():将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。
slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
splice():splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。
splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。
indexOf()和 lastIndexOf() (ES5新增):indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。
这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回1。在比较第一个参数与数组中的每一项时,会使用全等操作符。
forEach() (ES5新增)forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;第对应的数组索引,数组本身。
map() (ES5新增)map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
filter() (ES5新增)filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
every() (ES5新增)every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
some() (ES5新增)some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
reduce()和 reduceRight() (ES5新增)这两个方法都会实现迭代数组的所有项,然后构建一个最终返回的值。reduce()方法从数组的第一项开始,逐个遍历到最后。而 reduceRight()则从数组的最后一项开始,向前遍历到第一项。
这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。
传给 reduce()和 reduceRight()的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

字符串方法 *****

charAt() 返回指定索引位置的字符
charCodeAt() 返回指定索引位置字符的 Unicode 值
concat() 连接两个或多个字符串,返回连接后的字符串
fromCharCode() 将 Unicode 转换为字符串
indexOf() 返回字符串中检索指定字符第一次出现的位置
lastIndexOf() 返回字符串中检索指定字符最后一次出现的位置
localeCompare() 用本地特定的顺序来比较两个字符串
match() 找到一个或多个正则表达式的匹配
replace() 替换与正则表达式匹配的子串
search() 检索与正则表达式相匹配的值
slice() 提取字符串的片断,并在新的字符串中返回被提取的部分
split() 把字符串分割为子字符串数组
substr() 从起始索引号提取字符串中指定数目的字符
substring() 提取字符串中两个指定的索引号之间的字符
toLocaleLowerCase() 根据主机的语言环境把字符串转换为小写,只有几种语言(如土耳其语)具有地方特有的大小写映射
toLocaleUpperCase() 根据主机的语言环境把字符串转换为大写,只有几种语言(如土耳其语)具有地方特有的大小写映射
toLowerCase() 把字符串转换为小写
toString() 返回字符串对象值
toUpperCase() 把字符串转换为大写
trim() 移除字符串首尾空白
valueOf() 返回某个字符串对象的原始值

对象方法*****

Object.assign() 对象合并

46.手写防抖、节流,防抖和节流的区别 ***

https://www.jb51.net/article/105601.htm
https://blog.csdn.net/qq_29557739/article/details/96430431

47.浏览器渲染原理 ,回流,重绘 ***

https://blog.csdn.net/shelly1072/article/details/65654245

48. css3选择器优先级及计算 ***

!important(在样式属性后不加“;”,在!important后加分号)>行内样式>ID选择器>Class选择器>标签>通配符
相同级别:
(1)同一级别中后写的会覆盖先写的样式
(2)选择器约分
CSS优先级:是由四个级别和各级别出现次数决定的
四个级别:行内样式,ID选择器,Class选择器,标签
每个规则对应一个初始值0,0,0,0
若是 行内选择符,则加1、0、0、0
若是 ID选择符,则加0、1、0、0
若是 类选择符/属性选择符/伪类选择符,则分别加0、0、1、0
若是 元素选择符/伪元素选择符,则分别加0、0、0、1
算法:将每条规则中,选择符对应的数相加后得到的”四位数“,从左到右进行比较,大的优先级越高。

注意:
①、!important的优先级是最高的,但出现冲突时则需比较”四位数“;
②、优先级相同时,则采用就近原则,选择最后出现的样式;
③、继承得来的属性,其优先级最低;
!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
css选择器使用强烈建议采用低权重原则,利于充分发挥css的继承性,复用性,模块化、组件化。

移动端的1px线虚掉怎么解决 *

https://www.cnblogs.com/lunarorbitx/p/5287309.html

点击事件在移动端会有300毫秒延迟,为什么怎么解决 *

https://blog.csdn.net/weixin_46034375/article/details/107823692

移动端小刘海怎么解决 *

https://blog.csdn.net/qq814374557/article/details/78675845

vue

000 插件和组件的区别 **

Vue组件(component)用来构成你的App的业务模块,它的目标是App.vue。 引入 ,注册,html中作为标签名的形式使用
请说下封装 vue 组件的过程?
答:1. 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。(os:思考1小时,码码10分钟,程序猿的准则。)
  2. 准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。
  3. 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。
  4. 封装完毕了,直接调用即可

Vue插件(plugin) 用来增强你的技术栈的功能模块, 它的目标是Vue本身。(插件是对Vue的功能的增强和补充)
插件一般需要写成一个独立的js文件,需要安装,需要 引入,需要 use(使用)

插件的封装 **
https://www.jianshu.com/p/a6ba971bf7d2

我封装过tab标签的插件 ,封装过 弹窗的插件,封装过列表的插件,封装过瀑布式布局的插件
暴露的接口(可变的,用户可以向里面输入内容的,选择不同的显示状态的地方) ,
https://blog.csdn.net/weixin_43720095/article/details/88982224

vue项目webpack配置: ****

http://www.manongjc.com/article/54132.html

 publicPath: './',  //基本路径
 outputDir: 'dist',  //输出文件目录
 assetsDir:"static",//放置静态资源的目录
 indexPath:"index.html"//html的输出路径

   开发生产共同配置
      resolve: {
        alias: {
          '@': path.resolve(__dirname, './src'),
          '@c': path.resolve(__dirname, './src/components'),
          '@p': path.resolve(__dirname, './src/pages')
        }  别名配置
 
css配置
css: {
    extract: true, // 是否使用css分离插件 ExtractTextPlugin
    sourceMap: false, // 开启 CSS source maps?
    loaderOptions: {
      css: {}, // 这里的选项会传递给 css-loader
      postcss: {} // 这里的选项会传递给 postcss-loader
    }, // css预设器配置项 详见https://cli.vuejs.org/zh/config/#css-loaderoptions
    modules: false // 启用 CSS modules for all css / pre-processor files.
  },

  proxy 跨域的配置
   devServer: {
    open: process.platform === 'darwin',
    host: '0.0.0.0', // 允许外部ip访问
    port: 8022, // 端口
    https: false, // 启用https
    overlay: {
      warnings: true,
      errors: true
    }, // 错误、警告在页面弹出
    proxy: {
      '/api': {
        target: 'http://www.baidu.com/api',
        changeOrigin: true, // 允许websockets跨域
        // ws: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    } // 代理转发配置,用于调试环境
  },

https://www.cnblogs.com/jing-tian/p/11266796.html

vue webpack打包优化:****

1.babel-plugin-component ,减少js包的大小,将插件(如element-ui)和自己写的js分开打包,按需加载
2.路由懒加载:使用import(/webpackChunkName:“group-foo”/’./Foo.vue’)
可以完成按需加载页面,避免首页加载内容过多而导致的白屏问题
3.使用 UglifyPlugin (webpack.optimize.UglifyJsPlugin)对代码进行压缩
4.使用该插件image-webpack-loader 进行图片压缩

1: 引入:
require("image-webpack-loader")
2:配置:
  module: {
    rules: [
    ...(config.dev.useEslint ? [createLintingRule()] : []),
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options:   {
       loader: 'image-webpack-loader',
       options: {
        bypassOnDebug: true,
      }
    }
  },

5.由于webpack打包后的js过大,以至于在加载资源时间过长。所以将文件打包成多个js文件,在需要的时候按需加载

new commonsChunkPlugin({
 name:'charts',
 chunks:['commons'] 
 minChunks:function(module){
  return (
   module.resource &&
   /\.js$/.test(module.resource) &&
   module.resource.indexOf(
   path.join(__dirname, '../node_modules')
   ) === 0 && ['jquery.js', 'highcharts.js','echarts'].indexOf( module.resource.substr(module.resource.lastIndexOf('/')+1).toLowerCase() ) != -1
  )
 }
}) 
}

12.v-model的使用。 ***

答:v-model用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就做了两个操作:
v-bind绑定一个value属性;
v-on指令给当前元素绑定input事件。

16.$nextTick的使用 ***

答:当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。

##38.vue初始化页面闪动问题 ***
答:使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
首先:在css里加上[v-cloak] {
display: none;
}。
如果没有彻底解决问题,则在根元素加上style=“display: none;” :style="{display: ‘block’}"

##4.v-show和v-if指令的共同点和不同点? ***
答: 共同点:都能控制元素的显示和隐藏;
不同点:实现本质方法不同,v-show本质就是通过控制css中的display设置为none,控制隐藏,只会编译一次;v-if是动态的向DOM树内添加或者删除DOM元素,若初始值为false,就不会编译了。而且v-if不停的销毁和创建比较消耗性能。
总结:如果要频繁切换某节点,使用v-show(切换开销比较小,初始开销较大)。如果不需要频繁切换某节点使用v-if(初始渲染开销较小,切换开销比较大)。

##5.如何让CSS只在当前组件中起作用? ***
答:在组件中的style前面加上scoped

##6.vue优点? *****
答:轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
双向数据绑定:保留了angular的特点,在数据操作方面更为简单;
组件化:保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优势;
视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
虚拟DOM:dom操作是非常耗费性能的, 不再使用原生的dom操作节点,极大解放dom操作,但具体操作的还是dom不过是换了另一种方式;
运行速度更快:相比较与react而言,同样是操作虚拟dom,就性能而言,vue存在很大的优势。

##42. 写一个列表页需要考虑什么 *
这是个开放性问题
需要在性能上考虑这个问题
1.渲染时列表数据过多考虑分页、考虑做上拉加载更多页
2.列表内容需要封装为组件,在页面调用
3.列表数据传参时需要做参数格式验证
4.列表上有图片时考虑使用图片的懒加载,可以使用插件实现

1.1 vue项目打包优化 *****

https://segmentfault.com/a/1190000018217393
https://segmentfault.com/a/1190000016558958
https://www.cnblogs.com/llcdxh/p/9778491.html
https://blog.csdn.net/junkaicool/article/details/90906086

1. vue怎么做动画 *

1.Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

<div id="demo">
  <button v-on:click="show = !show"> Toggle</button>
  <transition name="fade"> <p v-if="show">hello</p></transition>
</div>
new Vue({
  el: '#demo',
  data: {show: true}
})
.fade-enter-active, .fade-leave-active { transition: opacity .5s;}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0;}

过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换。
v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
2.还可以使用css3的动画效果:

.bounce-enter-active {animation: bounce-in .5s;}
.bounce-leave-active { animation: bounce-in .5s reverse;}
@keyframes bounce-in {
  0% { transform: scale(0); }
  50% {  transform: scale(1.5);}
  100% { transform: scale(1);}
}

3.可以使用 js钩子

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>
methods: {
  // --------// 进入中// --------
  beforeEnter: function (el) {   // ...},
  // 当与 CSS 结合使用时 // 回调函数 done 是可选的
  enter: function (el, done) { // ... done() },
  afterEnter: function (el) {  // ...},
  enterCancelled: function (el) { // ...},
  // -------- // 离开时 // --------
 beforeLeave: function (el) {  // ...},
  // 当与 CSS 结合使用时
  // 回调函数 done 是可选的
  leave: function (el, done) { // ... done() },
  afterLeave: function (el) {// ...},
  // leaveCancelled 只用于 v-show 中
  leaveCancelled: function (el) { // ... }
}

4.可以引入Velocity

2.vue项目优化 *****

##
vue项目优化

长列表优化 。 将 table表格替换成其他标签 ,ul li ;分页和 触底加载下一页;onScroll 防抖节流;
需要看一下防抖节流 防抖和节流的区别和实现

3. vue新特性 ****

https://www.cnblogs.com/bob-zb/p/12481014.html

4.vue虚拟dom ***

虚拟dom是在内存生成一个虚拟的dom对象,来记录该节点的属性和方法,这样避免了直接操作真实dom节点,增加性能

5.vuex *****

vuex 流程
1.在组件中使用dispatch 将状态值分发action;
2.在actions中将 状态值commit提交到 mutations;
3.在mutations中修改store中的状态值;
4.当状态值发生变化时,自动触发render重新渲染页面。
vuex 属性 state action mutation module getter
vuex action mutation 区别 :action 可以异步, 大数据量的操作;mutation 可以直接更改store中的数据值

vuex getters 作用 相当于vue组件中的计算属性
vuex辅助函数 mapState mapAction mapMutation mapGetter
vuex与缓存区别
vuex刷新后数据就没有了,localStorage刷新后值还存在
vuex是响应式的,localStorage不是响应式的
vuex数据持久化 :vuex-persist

6. vue从a页面跳到b页面,b页面的值是从a页面带过来的,b页面刷新,a页面带过来的值没有了怎么解决

7.Vue生命周期 *****

1.什么是 vue 生命周期?有什么作用?
答:每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插件操作DOM节点,如想在页面渲染完后弹出广告窗, 那我们最早可在mounted 中进行。
2.第一次页面加载会触发哪几个钩子?
答:beforeCreate, created, beforeMount, mounted
3.简述每个周期具体适合哪些场景
答:beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
create:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
4.created和mounted的区别
答:created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
5.vue获取数据在哪个周期函数
答:一般 created/beforeMount/mounted 皆可.
比如如果你要操作 DOM , 那肯定 mounted 时候才能操作.
6.请详细说下你对vue生命周期的理解?
答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素 e l 和 ∗ ∗ 数 据 对 象 ∗ ∗ d a t a 都 为 u n d e f i n e d , 还 未 初 始 化 。 在 c r e a t e d 阶 段 , v u e 实 例 的 数 据 对 象 d a t a 有 了 , el和**数据对象**data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了, eldataundefinedcreatedvuedatael还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。

*** Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:

  • 加载渲染过程

    父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted

7.1 vue插槽 ***

在父组件调用子组件时,写在子组件标签中间的的内容,可以传递到子组件的slot标签的相应位置;
使用场景:类似于element-ui里面的组件封装,对组件的扩展,
匿名插槽:没名字
具名插槽:有名字
作用域插槽:所以作用域插槽是一种子传父传参的方式,解决了普通slot在parent中无法访问child数据的去问题

8.Vue的响应式原理, *****

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

整体思路
核心:通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的
要实现mvvm的双向绑定,就必须要实现以下几点:

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm入口函数,整合以上三者

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。
我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令(如v-model,v-on)对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下3个步骤,实现数据的双向绑定:

1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

2.实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。

3.0:
Vue3.x是用ES6的语法 Proxy对象来实现的,这个玩意儿也可以实现数据的劫持

相比于vue2.x,使用proxy的优势如下
1 defineProperty只能监听某个属性,不能对全对象监听
2 可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
3 可以监听数组,不用再去单独的对数组做特异性操作
vue3.x可以检测到数组内部数据的变化
https://www.cnblogs.com/houjl/p/12775091.html

8.vue-router实现路由懒加载( 动态加载路由 )****

https://blog.csdn.net/xm1037782843/article/details/88225104
答:三种方式
第一种:vue异步组件技术 ==== 异步加载,vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .但是,这种情况下一个组件生成一个js文件。
第二种:路由懒加载(使用import)。
第三种:webpack提供的require.ensure(),vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

9.Vue实现弹窗组件需要暴露哪些接口 ***

例如:暴露了width、title、确定按钮、取消按钮的事件函数、弹窗的内容,

<div id="app">
      <base-dialog width="30%" title="我的标题" :visible.sync="dialogVisible">
        <span>我是模态框的主体内容</span>
        <span slot="footer">
          <button class="btn danger">取消</button>
          <button class="btn primary">确定</button>
        </span>
      </base-dialog>
      <button @click="showM">显示模态框</button>
    </div>
    
    <!--模板-->
    <script type="text/template" id="myDialog">
      <div class="myDialog" v-if="visible">
        <div id="dialogMain" :style="{'width':width}" >
          <div id="dialogHeader">
            <span>{{title}}</span>
            <span @click="hiddenM">×</span>
          </div>
          <div id="dialogContent">
            <slot></slot>
          </div>
          <div id="dialogFooter">
            <slot name="footer"></slot>
          </div>
        </div>
      </div>
    </script>
    
    <script type="text/javascript">
      //1.创建模态框组件
      Vue.component('base-dialog',{
        props:['width','title','visible'],
        template:'#myDialog',
        methods:{
          hiddenM:function(){
            //将子组件的模态框的状态值传递给 父组件
            this.$emit('update:visible');
          }
        }
      });
      /***************************************************/
      var vm = new Vue({
        el:"#app",
        data:{
          dialogVisible:false
        },
        methods:{
          showM:function(){
            this.dialogVisible =true;
          }
        }
        
      })
    </script>

##10.Vue路由 ***
路由创建
路由跳转
路由传参

路由守卫,路由钩子 ***

1、全局钩子 beforeEach(全局前置守卫,如果你的项目中有一个以上的功能需要守卫建议使用 这个) afterEach beforeResolve (解析守卫)
2、某个路由的钩子 beforeEnter
3、组件内钩子
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave

参数:from to next
路由懒加载
子路由

##10.1 vue hash 和history的区别 ***
https://blog.csdn.net/lyn1772671980/article/details/80804419

##11.Vue使用函数式组件还是类组件 *
https://blog.csdn.net/weixin_41275295/article/details/100189869

##12. vue页面第一次渲染执行的几个钩子函数 ****
beforeCreate created beforeMounte mounted
##13. vue页面跳转时执行那几个钩子, ***
beforeCreate created beforeMounte mounted beforeDestory destoryed
##14. v-if v-for 在哪个钩子函数中解析 ***
当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级
避免 v-if 和 v-for 用在一起必要
永远不要把 v-if 和 v-for 同时用在同一个元素上
##15. vue前端路由原理 路由模式
history hash html5 历史记录

15.1 计算属性 ****

计算属性 watch ,计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新,与之相关的DOM部分也会同步自动更新。

计算属性有缓存,计算属性的函数会自动调用。普通函数需要手动触发

计算属性和watch ,异步操作或大数据量操作使用watch

1.watch擅长处理的场景:一个数据影响多个数据

2.computed擅长处理的场景:一个数据受多个数据影响

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

16.以下全局属性都是做什么用的 **

$props $attrs $listeners $root
$el $options $refs $watch() $emit $on $off $once

17. vue和jquery的区别 *

jquery对dom操作 是单向的

vue 使用双向绑定

18.$route $router的区别 ***

$route 当前页面路由
$router 全局的路由
$route为当前router跳转对象里面可以获取name、path、query、params等
r o u t e r 为 V u e R o u t e r 实 例 , 想 要 导 航 到 不 同 U R L , 则 使 用 router为VueRouter实例,想要导航到不同URL,则使用 routerVueRouterURL使router.push方法

17.vue组件中data为什么必须是一个函数? *****

答:因为JavaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。
  组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。

20.vue后台项目怎么做拦截 ***

axios 请求拦截 ,验证token ,防攻击
全局路由守卫,除了登录页面,其他页面都需要守卫
token有过期时间,在后台管理,如果过期了,会跳转到登录页,再重新获取token,token 保存到缓存

##21. v-if v-show区别为什么v-show没有else ***
v-if dom节点改变 少量切换使用
v-show 是css样式修改 大量切换使用show

23.vue常用的修饰符 *****

答:.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次。

38.vue初始化页面闪动问题 ***

答:使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
首先:在css里加上[v-cloak] {
display: none;
}。
如果没有彻底解决问题,则在根元素加上style=“display: none;” :style="{display: ‘block’}"

##22. 为什么有时候修改了值,可以打印修改的值,但是页面上不会改变 ****
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。
对于对象:
Vue 无法检测 property 的添加或移除
Vue 不能检测以下数组的变动:
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
当页面上的值不发生变化时,可以使用 $.set
对象还可以使用 :assign
数组还可以使用:splice

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。push() pop() shift() unshift() splice() sort() reverse()
也有非变更方法,例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。

23.用过哪些vue ui组件 element ui里面的

24.vue项目首页加载图标和地图插件很慢怎么解决 ??

27.vue组件传参 *****

父传子 : props接收

子传父: $emit 手动触发自定义事件 (因为 vue组件间传递数据时单向的)
兄弟: bus vuex(我)

https://blog.csdn.net/kangkang_90/article/details/92798296

http://www.mamicode.com/info-detail-3057151.html

  1. props/$emit

  2. $children/ $parent

  3. provide/ inject

    概念:

    provide/ injectvue2.2.0新增的api, 简单来说就是父组件中通过provide来提供变量, 然后再子组件中通过inject来注入变量。

    注意: 这里不论子组件嵌套有多深, 只要调用了inject 那么就可以注入provide中的数据,而不局限于只能从当前父组件的props属性中回去数据

4.ref / refs

5.eventBus

6.Vuex

7.localStorage / sessionStorage

8.$attrs$listeners

vue2.4中,为了解决该需求,引入了$attrs$listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下,父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外),将会“回退”且作为普通的HTML特性应用在子组件的根元素上

28.vue的路由守卫,原理 ?

29.vue的动态组件有哪些,是怎样实现的 ***

和计算属性一起使用的,组件的名字可以更改的组件
一般的动态组件的外面合一使用keep-alive进行缓存

30.vue的refs子组件是怎样接受的

31.vue如何创建一个路由表

32.nextTick的作用

33.vue3.0将mixin替换成了Composition API

34. vue项目中哪些部分使用了全局管道符,哪些地方使用了局部的

16.$nextTick的使用

答:当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。

43. vue项目中你做过哪些复杂编写,遇到的问题 ,解决方法

1.从详情页返回列表时保存浏览位置
用到keep-alive来缓存页面
当详情页中改变列表数据时,配合keep-alive,需要在vue钩子函数activated中,对数据进行更改
activated keep-alive组件激活时调用。
deactivated keep-alive组件停用时调用。
1.用到keep-alive来缓存页面
2.当详情页中改变列表数据时,配合keep-alive,需要在vue钩子函数activated中,对数据进行更改
3.在从其他页面进入时,页面要重新加载数据。页面从列表进入其他页面(非详情页)时,销毁当前的vue实例。此时需用到组件内的路由守卫,beforeRouteEnter和beforeRouteLeave
https://blog.csdn.net/fu983531588/article/details/90321827
https://www.cnblogs.com/goloving/p/9256212.html

  1. 路由全局守卫 router.beforeEach(to,from,next)
    当从一个路由跳转到另一个路由时触发此守卫,也叫全局前置守卫。
    所以它是跳转前触发的。任何路由跳转都会触发。
    每个守卫都有三个参数:
    to:这是你要跳去的路由对象;
    from:这是你要离开的路由对象;
    next:是一个方法,它接收参数;
    next() 跳转
    next(flase) 中断跳转
    next({path:"/"}) 中断跳转,跳转到一个新的路径
  2. axios拦截器
    使用axios 实现登录功能的流程(拦截器)
    先添加拦截器判断, 利用interceptors 调用request ,判断token 是否存在,如果存在,直接跳转

axios拦截器:
// 请求拦截,可以将请求的配置进行二次处理。
axios.interceptors.request.use(config=>{
// config 是axios的配置信息.
// console.log(config);
if(localStorage.token){
config.headers = {
authorization:localStorage.token
}
}
store.commit(“CHANGE_LOADING”,true);
config.url = “/ele”+config.url;
return config;
})

// 响应拦截
axios.interceptors.response.use(({data})=>{
console.log(44444444);
// 返回的值即是axios得到的值
store.commit(“CHANGE_LOADING”,false);
if(data.ok === 2 || data.ok === 3){
store.commit(“OUT_LOGIN”);
}else{
return data;
}

  1. css引用图片打包后找不到文件资源的问题
    css引入图片再打包后,style-loader无法设置自己的publicPath,所以只要改变style-loader中的publicPath即可,一行代码即可以搞定,
    找到build/util.js文件中ExtractTextPlugin的css路径,手动添加publicPath参数,
    if (options.extract) {
    return ExtractTextPlugin.extract({
    use: loaders,
    publicPath: ‘…/…/’,
    fallback: ‘vue-style-loader’
    })
    } else {
    return [‘vue-style-loader’].concat(loaders)
    }
    重新build一次,问题解决了

  2. mixin 可以提高代码的复用性,同时减少代码的耦合度,但是另一方面给代码维护造成了不小的困扰,用的时候需要衡量其使用频率。
    3.0时用新的 Composition API 提供了更好的解决方案

  3. 多了解一下vue的生命周期,包括公开的以及未公开的,必要时可以方便写个vue插件,在生命周期函数中注入新的功能,包括新的钩子函数,或者新的业务集成。比如:keep-alive的两个钩子

  4. 如有必要,destoryed钩子中手动回收一些变量或者注销一些事件,培养自己垃圾回收的意识,以免出现内存问题。如:定时器、事件的解除绑定、轮播的停止等

  5. 状态需要统一管理时考虑使用 vuex

  6. mounted钩子函数中请求数据导致页面闪屏问题
    其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了

  7. el-input手动获取焦点问题
    情景:输入框一开始是隐藏的,点击按钮显示输入框并获取焦点
    把手动获取焦点那段代码写在 n e x t T i c k ( ) 就 好 了 手 动 获 取 焦 点 这 个 操 作 我 也 记 录 一 下 : 首 先 给 标 签 加 个 属 性 r e f = " s e a r c h B o x " ( 名 字 随 便 起 ) , 然 后 点 击 按 钮 把 控 制 显 示 的 字 段 赋 值 t r u e , 接 着 写 下 这 几 行 代 码 就 好 了 t h i s . nextTick()就好了 手动获取焦点这个操作我也记录一下: 首先给标签加个属性ref="searchBox"(名字随便起),然后点击按钮把控制显示的字段赋值true,接着写下这几行代码就好了 this. nextTick()ref="searchBox"便,truethis.nextTick(() => {
    this.$refs.searchBox.focus()
    })

https://www.jianshu.com/p/13d5350c6d16
https://www.zhihu.com/question/387217498/answer/1153513847

vue中v-html会导致哪些问题

你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。

可能会导致xss攻击
V-html更新的是元素的 innerHTML 。内容按普通 HTML 插入, 不会作为 Vue 模板进行编译 。
但是有的时候我们需要渲染的html片段中有插值表达式,或者按照Vue模板语法给dom元素绑定了事件。
在单文件组件里,scoped 的样式不会应用在 v-html 内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对 v-html 的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局 style元素手动设置类似 BEM 的作用域策略。
后台返回的html片段,以及css样式和js,但是返回的js是不执行的,因为浏览器在渲染的时候并没有将js渲染,这时要在$nextTick中动
态创建script标签并插入
https://blog.csdn.net/qiumen/article/details/88119275

五、Vue的路由实现:hash模式 和 history模式

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

八、vue解决跨域问题的方法:

https://www.cnblogs.com/ldlx-mars/p/7816316.html

110 vue项目的兼容性问题处理

pc:
1、ES6语法不支持
解决方法:
引入babel-polyfill
npm install --save bable-polyfill
webpack.base.conf.js中修改为
app: [‘event-source-polyfill’, ‘babel-polyfill’, ‘./src/main.js’]
main.js 中引入
import ‘babel-polyfill’;
2、GET非首次请求时,IE默认使用缓存而不是去后台请求
解决方法:
在request拦截时,加时间戳
service.interceptors.request.use(config => {
// Do something before request is sent
// // 时间戳
if (config.method === ‘get’) {
config.params = {
t: Date.parse(new Date()) / 1000,
…config.params
}
}
return config;
}, error => {
// Do something with request error
console.log(error); // for debug
Promise.reject(error);
})
3、上传文件时,文件类型检查。如果为.apk文件,则file.type为" ".而jpg/png等文件正常
导致上传apk文件时,会报类型检查错误
解决方法:
export function validateApk(file) {
if (file.type === ‘application/vnd.android.package-archive’) {
return true;
} else {
if (file.name.substring(file.name.lastIndexOf(’.’) + 1) === ‘apk’) {
return true;
}
}
return false;
}

4、上传文件时,后台读取file.getName或者file.getOriginalName为全路径名称
解决方法:
后台去处理,如果为全路径,则进行字符串截取

IE目前已经放弃了自己的独特化,正一步步迎入互联网的主流怀抱。但迫于有用户存在,还是要兼容到IE8,9, 以上。
下面聊一下如何在vue框架中兼容IE
1.首先在index.html

// 添加请求meta 2. 安装npm install babel-cli --save 3.在webpack.base.conf.js 配置 entry: { app: ['babel-polyfill', './src/main.js'] // 在入口文件上进行修改,引入此插件,基本上可以使用大部分新的vue语法。 }, 4. 如果发现有图片没正常显示,或者样式稍微错乱 它把图片转化成了bese64, 设置图片百分比,外层盒子的宽度px。不建议使用rem.

问题:Vue2.0的官方脚手架工具构建的项目,chrome中跑一直没有问题,但ie打开出现了bug:

原因:Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。为了解决这个问题,我们使用一种叫做 Polyfill
(代码填充,也可译作兼容性补丁) 的技术。 简单地说,polyfill即是在当前运行环境中用来复制(意指模拟性的复制,而不是拷贝)尚不存在的原生 api 的代码。
方案:安装babel-polyfill

步骤
1.安装babel-polyfill
npm install --save-dev babel-polyfill
2.然后再main.js中引入
import 'babel-polyfill'
3.如果也是用了官方脚手架vue-cli,还需要在webpack.config.js配置文件中做各修改,用
module.exports = {
  entry: {
    app: ["babel-polyfill", "./src/main.js"]   // 替换 app: './src/main.js'
  } 
};

移动:
1.onclick事件的点穿点透 使用 ontap替换
2.移动端点击事件300ms延时 在头部的viewport 设置禁止缩放
3.iphone手机的小刘海,iphone手机的home键 https://blog.csdn.net/C__Two/article/details/106627613
https://imweb.io/topic/5baa38c279ddc80f36592efb

4.移动端1px线虚掉的问题
https://www.jianshu.com/p/3a262758abcf

十、如何给vue自定义组件添加点击事件?

需要在@click后面加上.native,官方对于native的解释为:
.native -——监听组件根元素的原生事件

vue项目做seo优化

https://blog.csdn.net/qq_40816649/article/details/92799569
https://blog.csdn.net/qq_42269433/article/details/106838947

vue中组件间传值的常用方法

1.父子组件间的传值:
父传子:01.使用props

  02. 使用$children获取子组件和父组件对象
  this.msg2=this.$children[0].msg
  03.使用$ref获取指定的子组件
      <m-child v-bind:msg="p2C" @showMsg='getChild' ref='child'></m-child>
this.c2P=this.$refs.child.msg33

子传父:01.使用 e m i t 传 递 事 件 给 父 组 件 , 父 组 件 监 听 该 事 件 02. 使 用 emit传递事件给父组件,父组件监听该事件 02.使用 emit02.使parent.获取父组件对象,然后再获取数据对象

mounted() {
    this.msg22 = this.$parent.msg2;
  }

2.非父子组件间传参:
01. 1.事件总线
    原理上就是建⽴一个公共的js文件,专门用来传递消息

bus.js
import Vue from 'vue'
export default new Vue
在需要传递消息的地⽅方引⼊入

import bus from './util/bus'
methods: {
  passMsg () {
    bus.$emit('msg', 'i am from app')
  }
},
      传递消息,在需要接受消息的地方使用bus.$on接受消息
mounted () {
    bus.$on('msg', (val) => {
      this.childMsg = val
    });

02.$attrs/listeners 用于多级组件间传值的问题
解决多级组件间传值的问题
$attr 将⽗组件中不包含props的属性传入子组件,通常配合 interitAttrs 选项
组件A传递到组件C,使用组件B作为桥梁A-B-C

组件A
<template>
  <div id="app">
    <!-- this is app -->
    <m-parent :msg="a" :msgb="b" :msgc="c"></m-parent>
  </div>
</template>
  组件B
<template>
  <div>
    <m-child  v-bind="$attrs"></m-child>
  </div>
</template>
 组件C    注意:如果组件C中有props属性接受的对象的化,组件A传递的对象就会被自动过滤掉
props: {
  msg: {
    type: String,
    default: ''
  },
}
 mounted () {
    console.log('attrs',this.$attrs)
  }

03.vuex

04多层父子组件通信 provide/inject。

有时需要实现通信的两个组件不是直接的父子组件,而是祖父和孙子,或者是跨越了更多层级的父子组件,这种时候就不可能由子组件一级一级的向上传递参数,特别是在组件层级比较深,嵌套比较多的情况下,需要传递的事件和属性较多,会导致代码很混乱。

这时就需要用到 vue 提供的更高阶的方法:provide/inject。

react

43.1 react项目中有哪些难点

1.react 与vue的区别

2.react 优化

3.react 新特性

1.context 可以跨组件传参

2.lazy、suspense 动态引入组件

3.memo 相当于 shouldComponentUpdate 使用在函数式组件中

4.hooks 同下

4. 使用hooks

在函数式组件中调用 state,调用钩子, useState, useEffect

5. setstate是异步还是同步,setState之后发生了哪些事情

  • setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。
  • setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。

6. react生命周期钩子函数

componentWillMount 去掉

render

componentDidMount

componentWillReceiveProps 去掉

shouldComponentUpdate 作用?函数式组件中 使用memo0

componentWillUpdate 去掉

componentDidUpdate

componentWillUnmount

1.React 中 keys 的作用是什么?

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。

render () {
return (


  • {this.state.todoItems.map(({item, key}) => {
    return
  • {item}

  • })}

)
}
在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。

2.调用 setState 之后发生了什么?

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

3.react 生命周期函数

初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:组件真正在被装载之后
运行中状态:
componentWillReceiveProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新描绘
componentDidUpdate:组件已经更新
销毁阶段:
componentWillUnmount:组件即将销毁

V17.0之后的版本删除的钩子函数
componentWillMount ,componentWillReceiveProps ,componentWillUpdate
在 v16.3以上版本新增的钩子函数
getDerivedStateFromProps,getSnapshotBeforeUpdate

4.shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?)

shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。
参考react 性能优化-sf

5.为什么虚拟 dom 会提高性能?(必考)

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
参考 如何理解虚拟 DOM?-zhihu

6.react diff 原理(常考,大厂必考)

把树形结构按照层级分解,只比较同级元素。
给列表结构的每个单元添加唯一的 key 属性,方便比较。
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.
选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
参考:React 的 diff 算法

7.React 中 refs 的作用是什么?

refs的适用情况:
1.处理焦点,文本选择,媒体控制
2.触发强制动画
3.继承第三方的dom库
4.如果可以通过声明能实现的,尽量避免使用refs
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回:
class CustomForm extends Component {
handleSubmit = () => {
console.log("Input Value: ", this.input.value)
}
render () {
return (

<input
type=‘text’
ref={(input) => this.input = input} />
Submit

)
}
}
上述代码中的 input 域包含了一个 ref 属性,该属性声明的回调函数会接收 input 对应的 DOM 元素,我们将其绑定到 this 指针以便在其他的类函数中使用。另外值得一提的是,refs 并不是类组件的专属,函数式组件同样能够利用闭包暂存其值:
function CustomForm ({handleSubmit}) {
let inputElement
return (
<form onSubmit={() => handleSubmit(inputElement.value)}>
<input
type=‘text’
ref={(input) => inputElement = input} />
Submit

)
}

8.如果你创建了类似于下面的 Twitter 元素,那么它相关的类定义是啥样子的?

{(user) => user === null ? : } import React, { Component, PropTypes } from 'react' import fetchUser from 'twitter' // fetchUser take in a username returns a promise // which will resolve with that username's data. class Twitter extends Component { // finish this } 如果你还不熟悉回调渲染模式(Render Callback Pattern),这个代码可能看起来有点怪。这种模式中,组件会接收某个函数作为其子组件,然后在渲染函数中以 props.children 进行调用:

import React, { Component, PropTypes } from ‘react’
import fetchUser from ‘twitter’
class Twitter extends Component {
state = {
user: null,
}
static propTypes = {
username: PropTypes.string.isRequired,
}
componentDidMount () {
fetchUser(this.props.username)
.then((user) => this.setState({user}))
}
render () {
return this.props.children(this.state.user)
}
}
这种模式的优势在于将父组件与子组件解耦和,父组件可以直接访问子组件的内部状态而不需要再通过 Props 传递,这样父组件能够更为方便地控制子组件展示的 UI 界面。譬如产品经理让我们将原本展示的 Badge 替换为 Profile,我们可以轻易地修改下回调函数即可:

{(user) => user === null ? : }

9.展示组件(Presentational component)和容器组件(Container component)之间有何不同

展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。
容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。

10.类组件(Class component)和函数式组件(Functional component)之间有何不同

类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 ‘无状态组件(stateless component)’,可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件(dumb components)或展示组件

11.(组件的)状态(state)和属性(props)之间有何不同

State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据–回调函数也可以通过 props 传递。

12.何为受控组件(controlled component)

在 HTML 中,类似 , 和 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一起被发送。但在 React 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state,重新渲染组件。一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为"受控元素"。

13.何为高阶组件(higher order component)

高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。

14.为什么建议传递给 setState 的参数是一个 callback 而不是一个对象

因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state。

15.除了在构造函数中绑定 this,还有其它方式吗

你可以使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调。

16. (在构造函数中)调用 super(props) 的目的是什么

在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props。

17. 应该在 React 组件的何处发起 Ajax 请求

在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。

18.描述事件在 React 中的处理方式。

为了解决跨浏览器兼容性问题,您的 React 中的事件处理程序将传递 SyntheticEvent 的实例,它是 React 的浏览器本机事件的跨浏览器包装器。

这些 SyntheticEvent 与您习惯的原生事件具有相同的接口,除了它们在所有浏览器中都兼容。有趣的是,React 实际上并没有将事件附加到子节点本身。React 将使用单个事件监听器监听顶层的所有事件。这对于性能是有好处的,这也意味着在更新 DOM 时,React 不需要担心跟踪事件监听器。

19.React 中有三种构建组件的方式

React.createClass()、ES6 class 和无状态函数。

20. react 组件的划分业务组件技术组件?

根据组件的职责通常把组件分为 UI 组件和容器组件。
UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。
两者通过 React-Redux 提供 connect 方法联系起来。

21.了解 redux 么,说一下 redux 把

redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer,工作流程是 view 调用 store 的 dispatch 接收 action 传入 store,reducer 进行 state 操作,view 通过 store 提供的 getState 获取最新的数据,flux 也是用来进行数据操作的,有四个组成部分 action,dispatch,view,store,工作流程是 view 发出一个 action,派发器接收 action,让 store 进行数据更新,更新完成以后 store 发出 change,view 接受 change 更新视图。Redux 和 Flux 很像。主要区别在于 Flux 有多个可以改变应用状态的 store,在 Flux 中 dispatcher 被用来传递数据到注册的回调事件,但是在 redux 中只能定义一个可更新状态的 store,redux 把 store 和 Dispatcher 合并,结构更加简单清晰
新增 state,对状态的管理更加明确,通过 redux,流程更加规范了,减少手动编码量,提高了编码效率,同时缺点时当数据更新时有时候组件不需要,但是也要重新绘制,有些影响效率。一般情况下,我们在构建多交互,多数据流的复杂项目应用时才会使用它们
redux 有什么缺点
一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。
当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断。

22.setState 同步异步问题

setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,
只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到
更新后的值,形式了所谓的“异步”,当然可以通过第二个参数setState(partialState,
callback)中的callback拿到更新后的结果。
setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件
和setTimeout中不会批量更新,在“异步”中如果对同一个值进行多次 setState ,
setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多
个不同的值,在更新时会对其进行合并批量更新。
想要获取到正确的state的值,必须在 setState的第二个参数(回调函数)中,

23.react新特性

context 可以跨组件传参,既从根节点可以直接传参到叶子节点
1.创建 const ThemeContext = React.createContext(‘light’);
2.传参

<ThemeContext.Provider value="dark">
      组件名
</ThemeContext.Provider>

3.接收

function MyButton(props){
  //3.接收参数
  return <ThemeContext.Consumer>{
    theme=><button className={theme}>按钮</button>
  }
  </ThemeContext.Consumer>
}

hooks
1.useState 可以在函数式组件中使用state ,并且可以调用函数更改state的值
2.useEffect useEffect它与 React 类中的 componentDidMount,componentDidUpdate,和
componentWillUnmount 有相同的功能,但是统一为单个 API。

memo
是在 函数式组件中,如果有组件不需要更新时,调用memo ,相当于 类组件中的 shouldComponentUpdate

lazy\Suspense\错误边界(Error boundaries)

24.redux-saga 和redux-thunk的区别:

redux-saga可以解决thunk 的两个问题:
1.action的形式不统一
2.就是异步操作太为分散,分散在了各个action中 不易维护
3.saga将异步操作放到统一的一个文件中处理

25.redux-saga的优缺点

优点:
(1)集中处理了所有的异步操作,异步接口部分一目了然
(2)action是普通对象,这跟redux同步的action一模一样
(3)通过Effect,方便异步接口的测试
(4)通过worker 和watcher可以实现非阻塞异步调用,并且同时可以实
现非阻塞调用下的事件监听
(5) 异步操作的流程是可以控制的,可以随时取消相应的异步操作。
缺点:太复杂,学习成本较高

26.redux-saga的effect (工具方法)

put:对应的是middleware中的dispatch方法,可以发送一个动作
call: 表示异步调用,其中call表示的是阻塞调用,
fork:表示异步调用,表示的是非阻塞调用。
take:监听action,返回监听到的action对象
delay:延时
takeEvery:予以相当于 on ,允许并发action
all:创建effect的描述信息,用来命令中间件,并行多个effect,并等待他们全部完成

27.react 项目优化

1.使用Fragment。减少不必要的节点生成,也可以使用空标签
2.类组件使用 shouldComponentUpdate,减少不必要的组件渲染
3.多使用 函数式组件渲染、减少使用类组件
4.函数式组件中使用 memo 避免重复渲染
5.使用React.lazy()和Suspense进行懒加载
6.异常捕获边界(Error Boundaries)
捕获发生异常的React组件。将异常组件和正常组件分割开。提高用户的体验性能。
7. 骨架屏
骨架屏插件以react-content-loader(svg图片生层)为基础。用于在页面初始加载时,避免出现白屏现象。
8.长列表优化
虚拟化长列表:只加载可视范围内的数据。
当网站需要加载大批量数据(成千上万)时,会加载特别慢。
这个时候我们可以使用“虚拟滚动”技术(react-window或者react-virtualized),只渲染当前屏幕范围内的数据。
鼠标滚动去触发事件,再渲染一屏。
9. 根据性能优化工具修改代码

  1. 使用Chrome的Performance工具
  2. React Devtools的Profiler工具分析;
    通过React.Profiler组件包裹需要分析渲染时间的组件(不适合生产环境)。
    10.SEO优化-预渲染
    使用prerender-spa-plugin的puppeteer(无头浏览器)功能。
    11.图片懒加载
    使用react-lazyload插件
    12.for循环中的key优化
    13.在使用了定时器的页面,页面离开时,停止未完成的渲染
    //解决 警告问题: Can’t perform a React state update on an unmounted component.
  componentWillUnmount = () => {
    //停止定时器
    clearInterval(this.inter);
    //如果页面跳转时,setState还没有执行完,就停止它,return
      this.setState = (state,callback)=>{
        return;
      };
  }

28.react路由传参

1.params

<Route path='/path/:name' component={Path}/>
<link to="/path/2">xxx</Link>
this.props.history.push({pathname:"/path/" + name});
读取参数用:this.props.match.params.name

优势 : 刷新地址栏,参数依然存在
缺点:只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。

2.query

<Route path='/query' component={Query}/>
<Link to={{ path : ' /query' , query : { name : 'sunny' }}}>
this.props.history.push({pathname:"/query",query: { name : 'sunny' }});
读取参数用: this.props.location.query.name

优势:传参优雅,传递参数可传对象;
缺点:刷新地址栏,参数丢失

3.state

<Route path='/sort ' component={Sort}/>
<Link to={{ path : ' /sort ' , state : { name : 'sunny' }}}> 
this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }});
读取参数用: this.props.location.query.state 

优缺点同query

4.search

<Route path='/web/departManange ' component={DepartManange}/>
<link to="web/departManange?tenantId=12121212">xxx</Link>
this.props.history.push({pathname:"/web/departManange?tenantId" + row.tenantId});
读取参数用: this.props.location.search

优缺点同params

小程序

1. 小程序中Switch跳转如何实现参数传递,

可以通过storage来缓存数据,跳转到指定页后获取storage,并清除数据

2. 简述下 wx.navigateTo(), wx.redirectTo(), wx.switchTab(), wx.navigateBack(), wx.reLaunch()的区别

wx.navigateTo():保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
wx.switchTab():跳转到 abBar 页面,并关闭其他所有非 tabBar 页面
wx.navigateBack()关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
wx.reLaunch():关闭所有页面,打开到应用内的某个页面

3.小程序父组件调用子组件函数

4.小程序优化

1、提高页面加载速度
2、用户行为预测
3、减少默认 data 的大小
4、组件化方案
控制包的大小
提升体验最直接的方法是控制小程序包的大小,基本上可以说,1M的代码包,下载耗时1秒左右。
控制包的大小的措施
压缩代码,清理无用的代码
图片放在cdn
采用分包策略
分包预加载
独立分包(版本要求有点高)
除了上面讲的控制包的大小,对异步请求的优化也很重要。
对异步请求的优化
onLoad 阶段就可以发起请求,不用等ready
请求结果放在缓存中, 下次接着用
请求中可以先展示骨架图
先反馈,再请求。比如说,点赞的按钮,可以先改变按钮的样式,再发起异步请求。
提升渲染性能
减少使用data,减少使用setData
合并setData的请求,减少通讯的次数
列表的局部更新,做分页,上拉加载更多页
onPageScroll,考虑使用防抖节流
尽可能使用小程序组件

5. 小程序的页面新建一个页面会添加4个文件

.wxml 相当于 html页
.wxss 相当于css页
.json 小程序页面的配置
.js 小程序的javascript页面

6.wxss 微信的css样式

​ 请谈谈WXSS和CSS的异同?
都是用来描述页面的样子;
WXSS 具有 CSS 大部分的特性,也做了一些扩充和修改;
WXSS新增了尺寸单位,WXSS 在底层支持新的尺寸单位 rpx;
WXSS 仅支持部分 CSS 选择器;
WXSS 提供全局样式与局部样式
WXSS 不支持window和dom 文档流

7.钩子函数

--7.1 App 注册小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。
钩子函数有:
属性	类型	默认值	必填	说明	最低版本
onLaunch	function		否	生命周期回调——监听小程序初始化。	
onShow	function		否	生命周期回调——监听小程序启动或切前台。	
onHide	function		否	生命周期回调——监听小程序切后台。	
onError	function		否	错误监听函数。	
onPageNotFound	function		否	页面不存在监听函数。	1.9.90
onUnhandledRejection
	
--getApp  获取小程序的实例
--var myApp = getApp();
--myApp.globalData.全局变量名  可以获取在app.js中定义的全局变量的值
--全局变量可以跨页面传参

--7.2 Page(Object object)
注册小程序中的一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
页面的钩子函数:
**onLoad	function			生命周期回调—监听页面加载   只执行一次的
**onShow	function			生命周期回调—监听页面显示   执行多次
**onReady	function			生命周期回调—监听页面初次渲染完成 只执行一次的
**onHide	function			生命周期回调—监听页面隐藏   执行多次
**onUnload	function			生命周期回调—监听页面卸载     只执行一次的
**onPullDownRefresh	function			监听用户下拉动作
**onReachBottom	function			页面上拉触底事件的处理函数
**onShareAppMessage	function			用户点击右上角转发
onPageScroll	function			页面滚动触发事件的处理函数
onResize	function			页面尺寸改变时触发,详见 响应显示区域变化
onTabItemTap	function			当前是 tab 页时,点击 tab 时触发

8.小程序中的事件

​ --事件分为冒泡事件和非冒泡事件:

bindtap冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
catchtap非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。  		

9. 小程序和普通网页开发的区别

1.1 网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应;
二者是分开的,分别运行在不同的线程中
1.2
页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作;
小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。
1.3
网页开发者需要面对的环境是各式各样的浏览器;
而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端
1.4网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。
小程序的开发则有所不同,需要经过申请小程序帐号、安装小程序开发者工具、配置项目等等过程方可完成。
1.5 网页 标签 div span img…
小程序 view text image button template block
1.6
普通的网页 做不到
小程序可以使用 api调用 手机底层接口 比如:获取摄像头、获取通讯录、获取相册…

10.小程序和原生App的区别

2.1 小程序无需安装、无需卸载,不占内存,用完即走
2.2 小程序的开发成本低,开发速度快
2.3 学习成本低 ,js,html,css 就可以开发小程序了
2.4 运行速度比原生的app慢
2.5 微信的客户群体大,推广容易

11.小程序的双向绑定和vue哪里不一样

小程序直接 this.data 的属性是不可以同步到视图的,必须调用:
this.setData({
// 这里设置
})

12.小程序页面间有哪些传递数据的方法

1.使用全局变量实现数据传递
在 app.js 文件中定义全局变量 globalData, 将需要存储的信息存放在里面
2.路由传参使用 wx.navigateTo 与 wx.redirectTo 的时候,可以将部分数据放在 url 里面,并在新页面 onLoad 的时候初始化
3.使用本地缓存 Storage 相关
4.使用模块,创建独立的模块文件,输出对象,
模块的使用,可以使用 封装好的js的对象进行传参 ,比如: utils/util.js

module.exports = {
  formatTime: formatTime,
  ggdata:'测试utils中数据是否能跨页传递'

}

在页面中使用时,用 require引入该模块文件
例如:

const util = reqiure("../../utils/util.js");

13. 微信小程序的优劣势

优势
即用即走,不用安装,省流量,省安装时间,不占用桌面
依托微信流量,天生推广传播优势
开发成本比 App 低
缺点
用户留存,即用即走是优势,也存在一些问题
入口相对传统 App 要深很多
限制较多,页面大小不能超过2M。不能打开超过10个层级的页面

14.如何实现下拉刷新

首先在全局 config 中的 window 配置 enablePullDownRefresh
在 Page 中定义 onPullDownRefresh 钩子函数,到达下拉刷新条件后,该钩子函数执行,发起请求方法
请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新

15.请谈谈wxml与标准的html的异同?

都是用来描述页面的结构;
都由标签、属性等构成;
标签名字不一样,且小程序标签更少,单一标签更多;
多了一些 wx:if 这样的属性以及 {{ }} 这样的表达式
WXML仅能在微信小程序开发者工具中预览,而HTML可以在浏览器内预览
组件封装不同, WXML对组件进行了重新封装,
小程序运行在JS Core内,没有DOM树和window对象,小程序中无法使用window对象和document对象。

16.你是怎么封装微信小程序的数据请求的?

在根目录下创建utils目录及api.js文件和apiConfig.js文件;
在appConfig.js封装基础的get\post\put\upload等请求方法,设置请求体,带上token和异常处理等,
封装了数据没获取过来时,旋转和加载中的提示,及数据返回后,返回promise对象,解决回调地狱问题;
在api.js中引入apiConfig.js封装好的请求方法,根据页面数据请求的urls,设置对应的方法并导出;
在具体页面导入;

小程序支持 ES6 语法 在返回成功的回调里面处理逻辑 Promise 异步 async/await

17.将一个页面的 wxml的数据传递到 js

1.使用 函数进行传参,
需要在 js文件中接收 ev的值
写法是:

  saveText: function(ev){
    console.log(ev.detail.value);
  },

2.给按钮绑定事件,需要传递 for循环中的数据的属性,比如:id

 <button class="del" bindtap="delFunc" data-id="{{item.id}}">删除</button>

在 js中接收数据:

delFunc:function(ev){
    console.log(ev);
    const id = ev.currentTarget.dataset.id;
  },

18.简述微信小程序原理?

小程序本质就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但又可以通过微信客户端调用原生的各种接口;
它的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现;
它从技术讲和现有的前端开发差不多,采用JavaScript、WXML、WXSS三种技术进行开发;
功能可分为webview和appService两个部分;
webview用来展现UI,appService有来处理业务逻辑、数据及接口调用;
两个部分在两个进程中运行,通过系统层JSBridge实现通信,实现UI的渲染、事件的处理等。

微信小程序采用JavaScript、wxml、wxss三种技术进行开发,与现有前端开发的区别:
JavaScript的代码是运行在微信APP中的,因此一些h5技术的应用需要微信APP提供对应的API支持;
wxml微信自己基于xml语法开发的,因此在开发时只能使用微信提供的现有标签,html的标签是无法使用的;
wxss具有css的大部分特性,但并不是所有都支持没有详细文档(wxss的图片引入需使用外链地址,没有body,样式可直接使用import导入)。
微信的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现。
小程序功能分为webview和APPservice,webview主要用来展示UI,appservice用来处理业务逻辑、数据及接口调用。它们在两个进程中进行,通过系统层JSBridge实现通信,实现UI的渲染、事件处理。

19. 请谈谈原生开发小程序、wepy、mpvue 的对比?

个人认为,如果是新项目,且没有旧的 h5 项目迁移,则考虑用小程序原生开发,好处是相比于第三方框架,坑少。
而如果有 老的 h5 项目是 vue 开发 或者 也有 h5 项目也需要小程序开发,则比较适合 wepy 或者 mpvue 来做迁移或者开发,近期看wepy几乎不更新了,所以推荐美团的mpvue。
而如果如果团队前端强大,自己做一套框架也没问题。

20.使用webview直接加载要注意哪些事项?

必须要在小程序后台使用管理员添加业务域名;
h5页面跳转至小程序的脚步必须是1.3.1以上;
微信分享只可以是小程序的主名称,如要自定义分享内容,需小程序版本在1.7.1以上;
h5的支付不可以是微信公众号的appid,必须是小程序的appid,而且用户的openid也必须是用户和小程序的

21.小程序调用后台接口遇到哪些问题?

数据的大小限制,超过范围会直接导致整个小程序崩溃,除非重启小程序;
小程序不可以直接渲染文章内容这类型的html文本,显示需借助插件
注:插件渲染会导致页面加载变慢,建议在后台对文章内容的html进行过滤,后台直接处理批量替换p标签div标签为view标签。然后其他的标签让插件来做。

22. webview中的页面怎么跳转回小程序?

wx.miniProgram.navigateTo({
url:’pages/login/login’+’$params’
})

//跳转到小程序导航页面

wx.miniProgram.switchTab({
url:’/pages/index/index’
})

##23.你说你负责支付环节,那么微信支付的 流程是否可以简单说一下?
临时凭证 获取 wxid
生成repayid
json,返回给小程序,小程序调支付窗口。
支持成功提示 + POST回调。

24.登录

a.使用wx.login获取code值
b.使用wx.request请求后台的api,把code值作为参数发送给后台
后台会根据我们传过去的code值来获取openid和session_key,后台需要调用数据库,将登录的信息进行保存,如果是第一次登录,会生成一条新的注册记录

    把微信账号登录态生成一个session id并维护在我们自己的session机制中,然后把登录成功的状态返回到小程序客户端作为已经登录成功的凭证。并且返回token值。

c.把登录成功的状态的session值保存到本地,使用wx.setStorage把token保存到本地,
d.在你需要使用的地方session_id的地方调用wx.getStorage(建议你也可以封装一个方法,就可以很方便的取出你要的数据)
e.登录成功后,需要 if (res.authSetting[‘scope.userInfo’]) {
//如果返回true表示 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
如果授权成功,调用 wx.getUserInfo ,获取用户信息,保存到 this.globalData中
注意:有的网站,登录成功后,还有一个手机绑定的功能,获取该微信的手机号,使用wx.request传到后台,与相应的注册账号进行绑定

25.支付流程

25.1 支付之前的准备工作 ,微信账号是企业级的,需要认证,需要申请小程序支付,并获得小程序支付的后台账号,
并且配置好后台的对公账号,打较少的钱,测试账号是否可用

25.2 首先判断是否是已经登录状态,如果不是就跳转登录
25.3 如果已经登录完,我们根据一个用户表将id和openid联系起来,对应openID的id则是用户的uid,生成token,保存缓存
25.4 调用后台 统一下单接口,获取prepay_id,获取所有的签名信息,保存缓存中
25.5 在小程序中调用后台的 order订单接口,获取订单信息,在后台创建商品订单,在订单中会保存商品的id、名称、数量…;如果订单创建成功,将订单内容保存到缓存;
25.6 如果订单创建成功,使用 wx.request调用后台的支付接口 ‘/pay/pre_order’,进行后台的支付流程;
在 success的回调中 ,调用 wx.requestPayment ,请求小程序的支付,在请求的参数中传递 签名信息和商品信息;如果返回 success,那么表示支付成功;如果失败则提示支付失败,并跳转到 未支付页面

【支付流程】https://blog.csdn.net/qq_38378384/article/details/80882980

[小程序面试题]https://www.cnblogs.com/changxin7/p/12334950.html

##常识类:
##1. 与后台调试接口
##2.与ui的配合

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值