2021学习笔记WEB

Vue.js中this.$nextTick()的使用

Vue.js中this. n e x t T i c k ( ) 的使用 t h i s . nextTick()的使用 this. nextTick()的使用this.nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

vue面试题合集
vue面试题合集
vue面试题搜索列表
JS的八大数据类型

js合并两个对象的方法

ES6之前就循环遍历咯,ES6浅拷贝的话可以用**Object.assign();**当然你如果项目里有jquery/underscore/lodash甚至是angular一般都有类似的extend方法咯。
jquery有一个继承方法 $.extend() ,可以直接用

1.1 $.extend()-------- JQ

var obj1= {
    
    'a': 1};
var obj2= {
    
    'b': 1};
var c = $.extend(obj1, obj2);
console.log(obj1); // {a: 1, b: 1} obj1已被修改
//或者
var obj3 = $.extend({
    
    }, obj1, obj2)
console.log(obj3);//{a: 1, b: 1} 不会改变obj1,obj21.2 遍历赋值

1.2 遍历赋值 -------- JS

var obj1={
    
    'a':1};
var obj2={
    
    'b':2,'c':3};
for(var key in obj2){
    
    
  if(obj2.hasOwnProperty(key)===true){
    
    
  //此处hasOwnProperty是判断自有属性,使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问会避免原型对象扩展带来的干扰
  obj1[key]=obj2[key];
  }
}
console.log(obj1);//{'a':1,'b':2,'c':3};

1.3 Obj.assign()-------- ES6
可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

Object.assign(target, ...sources)
//a. 复制一个对象<br>var obj = { a: 1 ,b:2};
var copyObj = Object.assign({
    
    }, obj);
console.log(copyObj); // { a: 1,b:2 }//b.合并多个对象
var o1 = {
    
     a: 1 };
var o2 = {
    
     b: 2 };
var o3 = {
    
     c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 且目标对象自身也会改变。

2 对象的深拷贝和浅拷贝

2.1 浅拷贝

// 浅拷贝
var obj1={
    
    'a':1}; 
var obj2={
    
    'b':{
    
    'b1':22,'b2':33}};
 
$.extend(obj1, obj2);   //obj1拷贝了obj2的属性
 
console.log(obj1)  // {'a':1,'b'{'b1':22,'b2':33}}
console.log(obj1.b.b1)  // 22
 
obj2.b.b1=44;   //obj2重新赋值
console.log(obj1.b.b1)  // 44  obj1.b仅拷贝了对象的指引,所以受原obj2的影响

2.2 深拷贝

// 深拷贝
var obj1={
    
    'a':1};
var obj2={
    
    'b':{
    
    'b1':22,'b2':33}};
 
$.extend(true,obj1, obj2);   //第一个参数设为true表示深复制
 
console.log(obj1)  // {'a':1,'b'{'b1':22,'b2':33}}
console.log(obj1.b.b1)  // 22
 
obj2.b.b1=44;   //obj2重新赋值
console.log(obj1.b.b1)  // 22 obj1拷贝了obj2的所有属性以及值,并不受obj2的影响

什么是原型链?

答案:通过一个对象的__proto__可以找到它的原型对象,原型对象也是一个对象,就可以通过原型对象的__proto__,最后找到了我们的 Object. prototype, 从实例的原型对象开始一直到 Object. prototype 就是我们的原型链,
JavaScript 中所有的对象都是由它的原型对象继承而来。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链

图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线
图中由相互关联的原型组成的链状结构就是原型链,即蓝色的这条线
翻转一下就是这样

JavaScript中的原型与原型链
JavaScript中的原型与原型链

事件循环

微任务和宏任务

  • 宏任务

  • 分类: setTimeout setInterval requrestAnimationFrame

    1. 宏任务所处的队列就是宏任务队列
    1. 第一个宏任务队列中只有一个任务: 执行主线程的js代码
    1. 宏任务队列可以有多个
    1. 当宏任务队列的中的任务全部执行完以后会查看是否有微任务队列如果有先执行微任务队列中的所有任务,如果没有就查看是否有宏任务队列
  • 微任务

  • 分类: new Promise().then(回调) process.nextTick

    1. 微任务所处的队列就是微任务队列
    1. 只有一个微任务队列
    1. 在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中的所有任务
 * */
console.log('----------------- start -----------------');
setTimeout(() => {
    
    
    console.log('setTimeout');
}, 0)

new Promise((resolve, reject) => {
    
    
    for (var i = 0; i < 5; i++) {
    
    
        console.log(i);
    }
    resolve(); // 修改promise实例对象的状态为成功的状态
}).then(() => {
    
    
    console.log('promise实例成功回调执行');
})

console.log('----------------- end -----------------');

在这里插入图片描述

页面从输入 URL 到显示,过程

浏览器地址栏输入 url
浏览器会先查看浏览器缓存–系统缓存–路由缓存,如有存在缓存,就直接显示。如果没有,接着第三步
域名解析(DNS)获取相应的 ip
浏览器向服务器发起 tcp 连接,与浏览器建立 tcp 三次握手
握手成功,浏览器向服务器发送 http 请求,请求数据包
服务器请求数据,将数据返回到浏览器
浏览器接收响应,读取页面内容,解析 html 源码,生成 DOm 树
解析 css 样式. 浏览器渲染,js 交互绑定多个域名,数量不限;

闭包的理解?优缺点?

概念:闭包就是能够读取其他函数内部变量的函数

三大特性:
函数嵌套函数。
函数内部可以引用外部的参数和变量。
参数和变量不会被垃圾回收机制回收。
优点:
希望一个变量长期存储在内存中。
避免全局变量的污染。
私有成员的存在。
缺点:
常驻内存,增加内存使用量。
使用不当会很容易造成内存泄露。
使用场景
在进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果。

防抖和节流

  • 防抖
    含义:持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。

简单的防抖代码:

function debounce(fn, wait) {
    
        
    var timeout = null;    
    return function() {
    
            
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}
// 处理函数
function handle() {
    
        
    console.log(Math.random()); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));

在持续触发scroll事件时,事件处理函数handle只在停止滚动1000毫秒后才会被调用一次,就是说在持续触发事件的过程中,事件处理函数handle一直都没有执行。

  • 节流

含义:当持续的触发事件时,在一段时间只调用一次事件处理函数。
持续的触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次函数。
实现:
实现函数节流主要有两种方式,时间戳与定时器

1、时间戳实现

当高频事件触发时,第一次会立即执行,给事件绑定函数与真正触发事件的间隔一般大于delay,而后在频繁的触发事件,都是delay事件才执行一次。而当最后一次时间触发结束以后,事件也不会再执行。

var throttle = function(func, delay) {
    
                
  var prev = Date.now();            
  return function() {
    
                    
    var context = this;                
    var args = arguments;                
    var now = Date.now();                
    if (now - prev >= delay) {
    
                        
      func.apply(context, args);                    
      prev = Date.now();                
    }            
  }        
}        
function handle() {
    
                
  console.log(Math.random());        
}        
window.addEventListener('scroll', throttle(handle, 1000));

2、定时器实现:
在触发事件时,设置一个定时器,再次触发事件时,若定时器存在,就不执行,知道delay时间后,定时器执行函数,并且清空定时器,继续设置下一个定时器。

var throttle = function(func, delay) {
    
                
    var timer = null;            
    return function() {
    
                    
        var context = this;               
        var args = arguments;                
        if (!timer) {
    
                        
            timer = setTimeout(function() {
    
                            
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}        
function handle() {
    
                
    console.log(Math.random());        
}        
window.addEventListener('scroll', throttle(handle, 1000));

第一次触发事件,不会立即执行函数,而是在delay后执行,之后再频繁的触发,也都是再delay时间执行一次,当最后一次停止触发后,由于定时器的delay延迟,可能还会执行一次函数。

  • 总结
    函数防抖:原理就是维护一个计时器,规定时间后触发函数,但是在规定时间内再次触发的话,就会取消之前的定时器重新设置,这样只有最后一次操作才会被触发。
    函数节流:在一定时间内只触发一次函数,原理是通过判断是否到达一定时间来触发函数。
  • 两者的区别:
    节流是不管事件触发多频繁,保证规定时间内一定会执行一次真正的事件处理函数;
    防抖只是在最后一次事件后才触发函数。在页面的无线加载场景下,我们需要用户在滚动页面时,每隔一段事件发一次AJAX请求,而不是在用户停止滚动页面操作才去请求数据。这种就需要节流来实现。

JS单线程、异步、同步概念 ,事件循环

从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件循环。在此之前需要了解JS单线程,及由此产生的同步执行环境和异步执行环境。
  众所周知,JS是单线程(如果一个线程删DOM,一个线程增DOM,浏览器傻逼了~所以只能单着了),虽然有webworker酱紫的多线程出现,但也是在主线程的控制下。webworker仅仅能进行计算任务,不能操作DOM,所以本质上还是单线程。
  单线程即任务是串行的,后一个任务需要等待前一个任务的执行,这就可能出现长时间的等待。但由于类似ajax网络请求、setTimeout时间延迟、DOM事件的用户交互等,这些任务并不消耗 CPU,是一种空等,资源浪费,因此出现了异步。通过将任务交给相应的异步模块去处理,主线程的效率大大提升,可以并行的去处理其他的操作。当异步处理完成,主线程空闲时,主线程读取相应的callback,进行后续的操作,最大程度的利用CPU。此时出现了同步执行和异步执行的概念,同步执行是主线程按照顺序,串行执行任务;异步执行就是cpu跳过等待,先处理后续的任务(CPU与网络模块、timer等并行进行任务)。由此产生了任务队列与事件循环,来协调主线程与异步模块之间的工作。
** 事件循环机制**
js遇到ajax、setTimeout等有时间延迟的任务,将这类任务交给相应的的异步模块处理,同时主线程就可以并行处理其他的操作。当异步处理完成,主线程空闲时读取相应的callback.,进行后续的操作,提高了CPU的利用率。

webpack打包优化

  1. 提取可服用的组件,函数 2. 删除无用代码模块 3. 非首屏的资源文件按需异步加载 4. 单页面应用,分割js 代码优化加载时间 5. 利用缓存加快下一次加载时间

vue 2和3的区别

https://m.php.cn/vuejs/464077.html
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过new Proxy()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
Vue 3.0与Vue 2.0的区别仅是数据劫持的方式由Object.defineProperty更改为Proxy代理,其他代码不变。

vuex组成

1、State——数据仓库
(数据状态定义在这里)vuex的数据都存储于state中,数据唯一源,属于 json 对象
2、getter——用来获取数据的
(相当于派生出来的,正常通过实例State也可以获取)
3、Mutation——修改数据
(需要commit一个Mutation来进行修改,这样就可对状态的修改进行一个历史记录,方便于监听和回滚等)Mutation的操作一定是同步的,如果写成异步的会很繁琐。
4、Action——用来提交mutation
Action常用于异步操作状态数据,Mutation用于同步操作状态数据(相当于包装了一层)
5、 model 模块

  • vuex使用场景:
    1、多个试图依赖于同一状态
    (例如:用户信息在多个页面都需要使用,此时就可以定义在vuex中),也就是多组件之间的状态共享【状态共享】【读】
    2、来自不同视图的行为需要改变同一个状态
    (例如:用户会员到期,此时页面时一些其他有会员特性的地方就不应该出现)【状态响应式改变】【写】

Vue中computed watch的区别

computed 计算属性

计算属性基于 data 中声明过或者父组件传递的 props 中的数据通过计算得到的一个新值,这个新值只会根据已知值的变化而变化,简言之:这个属性依赖其他属性,由其他属性计算而来的

  • computed 带有缓存功能

computed 内定义的 function 只执行一次,仅当初始化显示或者相关的 data、props 等属性数据发生变化的时候调用;

而 computed 属性值默认会缓存计算结果,计算属性是基于它们的响应式依赖进行缓存的;

只有当 computed 属性被使用后,才会执行 computed 的代码,在重复的调用中,只要依赖数据不变,直接取缓存中的计算结果。只有依赖型数据发生改变,computed 才会重新计算。
computed 中的属性都有一个 get 和一个 set 方法,当数据变化时,调用 set 方法,可实现数据的双向绑定

  • watch 监听属性

通过 vm 对象的 $watch() 或 watch 配置来监听 Vue 实例上的属性变化,或某些特定数据的变化,然后执行某些具体的业务逻辑操作。当属性变化时,回调函数自动调用,在函数内部进行计算。其可以监听的数据来源:data,props,computed 内的数据。
 
- 总结:
  watch和computed都是以Vue的依赖追踪机制为基础的,当某一个依赖型数据(依赖型数据:简单理解即放在 data 等对象下的实例数据)发生变化的时候,所有依赖这个数据的相关数据会自动发生变化,即自动调用相关的函数,来实现数据的变动。

当依赖的值变化时,在watch中,是可以做一些复杂的操作的,而computed中的依赖,仅仅是一个值依赖于另一个值,是值上的依赖。

应用场景:
  computed:用于处理复杂的逻辑运算;一个数据受一个或多个数据影响;用来处理watch和methods无法处理的,或处理起来不方便的情况。例如处理模板中的复杂表达式、购物车里面的商品数量和总金额之间的变化关系等。
  watch:用来处理当一个属性发生变化时,需要执行某些具体的业务逻辑操作,或要在数据变化时执行异步或开销较大的操作;一个数据改变影响多个数据。例如用来监控路由、inpurt 输入框值的特殊处理等。

区别:  
computed

  • 初始化显示或者相关的 data、props 等属性数据发生变化的时候调用;
  • 计算属性不在 data 中,它是基于data 或 props 中的数据通过计算得到的一个新值,这个新值根据已知值的变化而变化;
  • 在 computed 属性对象中定义计算属性的方法,和取data对象里的数据属性一样,以属性访问的形式调用;
  • 如果 computed 属性值是函数,那么默认会走 get 方法,必须要有一个返回值,函数的返回值就是属性的属性值;
  • computed属性值默认会缓存计算结果,在重复的调用中,只要依赖数据不变,直接取缓存中的计算结果,只有依赖型数据发生改变,computed才会重新计算;
  • 在computed中的,属性都有一个 get 和一个 set 方法,当数据变化时,调用 set 方法。
    watch
  • 主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看作是 computed 和 methods 的结合体;
  • 可以监听的数据来源:data,props,computed内的数据;
  • watch支持异步;
  • 不支持缓存,监听的数据改变,直接会触发相应的操作;
  • 监听函数有两个参数,第一个参数是最新的值,第二个参数是输入之前的值,顺序一定是新值,旧值。

前端浏览器的几种存储方式

前端存储3种方式

vue中data为什么必须是函数

首先定义的
xx.vue文件在编译之后是一个类,每个地方使用这个组件的时候,相当于对这个类实例化,在实例化的时候执行data,如果不是一个函数的话,每个组件的实例的data都是同一个引用数据,当该组件作为公共组件共享使用,一个地方的data更改,所有的data一起改变。如果data是一个函数,每个实例的data都在闭包当中,就不会各自影响了

  • 根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
  • 组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数都会返回全新data对象 原文链接:

vue中query与params传参的区别

主要区别

  • query传参,参数会拼接到页面路径,页面跳转后刷新也可正常取值,路由跳转路径需要用path;
  • params传参,参数不会拼接到页面路径,页面跳转后刷新值不存在,路由跳转路径需要用name
    query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
    讲解:
    比如详情页,要求按F5刷新完后数据还是能正常展示,详情页是在created后用ID请求。如果是用query 传递过来的id,在this.$route,上会一直存在。
    但是如果用params的时候,如果不做别的配置,直接在路由跳转的时间加params,F5刷新数据可能就不存在了。
    如果一定要用params也可以,在router文件的 path 后面 + “/:id”,这样页面F5刷新后ID还是在router中。
    如果是单独的详情页这样也是可以的,但是如果新增和编辑都是跳转同一个路由呢,这样就会报错了,因为编辑要请求详情,就需要ID,但是新增的时候是没有ID的,这时候就需要 path 后面 + “/:id?”,也就是id后面加一个“?”,和正则的意思一样,可有可无。这样就不会报错了。

个人还是建议用 query ,因为它不需要改变 path规则。

Set 和 Map 数据结构

ES6中提供了Set数据容器,这是一个能够存储无重复值的有序列表
Map集合内含多组键值对,通常用来缓存频繁取用的数据。
可以理解为2种数据结构特性
ES6–Set、Map及Symbol

什么是跨域,解决方式

跨域:(CORS)指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对js施加的安全限制。
同源策略:协议,域名,端口都要相同,其中有一个不同都会产生跨域.
解决跨域:

  • Node.js 中推荐使用 cors 模块
  • JSONP 浏览器是允许像 link、img、script 标签在路径上加载一些内容进行请求,是允许跨域的,那么 jsonp 的实现原理就是在 script 标签里面加载了一个链接,去访问服务器的某个请求,返回内容。
  • Nginx 代理服务器配置跨域 nginx实现跨域的原理,实际就是把web项目和后端接口项目放到一个域中,这样就不存在跨域问题,然后根据请求地址去请求不同服务器(真正干活的服务器);
    详细讲解

https和http区别?

https解决http数据明文传输不安全问题,但是在对传输数据加密后,要把加密规则告诉客户端,但是又怕加密规则在传输的途中,被拦截破解导致传输数据可能被串改的风险,引入了一个认证机制(CA),把加密规则通过认证机制生成数字证书,然后客户端再通过认证机制校验证书,如果未被修改则获取到加密规则后对数据进行解密;

编程题目

在这里插入图片描述

用js实现读取出字符串中每个字符重复出现的次数?

var的执行提升问题-console.log(a); var a=10; console.log(a);

call()、applay()以及bind()三者之间的区别

Vue组件强制刷新(重新渲染)的四种方案

  • 刷新整个页面(最low的,可以借助route机制)
  • 使用v-if标记(比较low的)
  • 使用内置的forceUpdate方法(较好的 )—内置**$forceUpdate**,使用前需要在配置中启用
  • 使用key-changing优化组件(最好的)-----原理,vue使用key标记组件身份,当key改变时就释放原始组件,重新加载新的组件。

后台管理系统的权限控制与管理

实现节流函数
重绘 :颜色形状改变 、重排:大小位置改变

猜你喜欢

转载自blog.csdn.net/qq_21113235/article/details/114274471