P7面试题库(某企业面试题库)

注意:加粗的字体为速记的文本(核心点)

1、 响应式布局如何实现

响应式布局可以让网站同时适配不同分辨率和不同的手机端,让客户有更好的体验。
方案一:百分比布局
利用对属性设置百分比来适配不同屏幕,注意这里的百分比是相对于父元素; 能够设置的属性有 width、height、padding、margin,其他属性比如 border、font-size 不能用百分比设置的,先看一个简单例子:
顶部是利用设置图片 width: 50%来适应不同的分辨率,由于原始图片高度不同,所以第一张图片顶部会有空白,这种情况最好两张图片宽高保持一致,如果使用强制高度统一,会导致图片变形;
注意:当屏幕大于图片的宽度时,会进行拉伸;解决拉伸方法就是改为
max-width: 50%,但当屏幕大于图片的宽度时,两边会有空白。栏目是利用设置单栏目 width: 25%来适应不同的分辨率。
由于没办法对 font-size 进行百分比设置,所以用的最多就是对图片和大块布局进行百分比设置。
方案二:媒体查询 (CSS3 @media 查询)
利用媒体查询设置不同分辨率下的css 样式,来适配不同屏幕,先看一个简单例子:
三个不同分辨率下显示对应的背景色。
媒体查询相对于百分比布局,可以对布局进行更细致的调整,但需要在每个分辨率下面都写一套 css 样式;分辨率拆分可视项目具体情况而定。
注意:IE6、7、8 不支持媒体查询。
方案三.rem 响应式布局
当前页面中元素的rem 单位的样式值都是针对于html 元素的font-size 的值进行动态计算的,所以有两种方法可以达到适配不同屏幕:
第一种利用媒体查询,在不同分辨率下给 html 的 font-size 赋值。第二种利用 js 动态计算赋值,缺点就是打开页面时候,元素大小会有一个变化过程
方案四.vw 响应式布局
根据 PSD 文件宽度或高度作为标准,元素单位 px 转换为 vw 或 vh,比如font-size: 12px,PSD 文件宽度 375,转换公式 12 * 100 / 375,则样式改为font-size: 3.2vw,下面是我经常使用的工具,有利于提高转换效率。
现阶段手机端用的最多就是这个方法,能保持不同屏幕下元素显示效果一致, 也不用写多套样式。
方案五.flex 弹性布局
利用 flex 属性来适配不同屏幕,下图利用简单的属性实现栏目响应式
方案六:流式布局(百分比布局)
方案七:h5布局(bodstrap)

2、 rem 布局原理

rem:相对于根元素(即 html 元素)font-size 计算值的倍数。通俗的说,1rem = html 的 font-size 值
这段代码。a 标签的 font-size 值为 0.5rem,实际就是 100px*0.5=50px。
html{font-size:100px;} a{font-size:.5rem;}
如何使用 rem 进行布局?
1.标签的 rem 单位的值怎么计算

通过使用 rem + js 改变 html 标签的 font-size(整体缩放)实现兼容性更高的页面下面来举个例子,
当我们拿到的设计图是 750px 的时候,窗口宽度 750px,html 的 font-size 的大小为
100px;
也就是说 1rem = 100px;所以标题的 font-size 的大小为 26/100=.26rem;

2.如何实现兼容各种屏幕大小的设备

使用到 javascript 来动态改变 html 标签 font-size 的大小,其他的 rem 单位的数值就会被浏览动态计算转为 px 单位,从而达到和设计图高度的相似。
当屏幕 750px 的时候,html 的 font-size 值是 100px;窗口大小变化的时候,可以通过js 获取到窗口大小。
这时候获取到一个比例 750:100=获取到的屏幕大小:html 标签的 px 单位的值以下 js 代码,用于实现根据获取到的屏幕大小,动态修改 html 标签的 px 单位的值

3、箭头函数和普通函数的区别

为了解决普通函数this指向问题

  • 是匿名函数,不能作为构造函数,不能使用new,

    箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式:一种只包含一个表达式,连{ …
    }和return都省略掉。还有一种可以包含多条语句,这时候就不能省略{ … }和return。

    箭头函数内没有arguments,可以用展开运算符…解决,arguments是参数的集合, 是一个类数组/伪数组体现在他不能调用数组的方法

    箭头函数的this,始终指向父级上下文(箭头函数的this取决于定义位置父级的上下文,跟使用位置没关系,普通函数this指向调用的那个对象)

    箭头函数不能通过call() 、 apply()、bind()方法直接修改它的this指向。(call、aaply、bind会默认忽略第一个参数,但是可以正常传参)

    箭头函数没有原型属性

4、 数据类型判断

1.typeof typeof 对于基本数据类型判断是没有问题的,但是遇到引用数据类型(如:Array)是不起作用
2.instanceof 判断 new 关键字创建的引用数据类型
不考虑 null 和 undefined(这两个比较特殊)以对象字面量创建的基本数据类型

3.constructor constructor 似乎完全可以应对基本数据类型和引用数据类型 但如果声明了一个构造函数,并且把他的原型指向了 Array 的原型,所以这种情况下,constructor 也显得力不从心
4.Object.prototype.toString.call() 完美的解决方案
5.jquery.type() 无敌万能的方法

5、 类组件(Class component)和函数式组件(Functional component)之间有何不同?

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

6、 原型和原型链

1、原型的概念
JavaScript 的所有对象中都包含了一个 [proto] 内部属性,这个属性所对应的就是自身的原型
JavaScript 的函数对象,除了原型 [proto] 之外,还有 prototype 属性,当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为 实例对象的

原型 [proto]
2、原型链的概念
当一个对象调用自身不存在的属性/方法时,就会去自己 [proto] 关联的前辈 prototype 对象上去找,如果没找到,就会去该 prototype 原型 [proto] 关联的前辈 prototype 去找。依次类推,直到找到属性/方法或 undefined 为止。从而形成了所谓的“原型链”。
3、总结
JavaScript 中的对象,都有一个内置属性[Prototype],指向这个对象的原型对象。当查找一个属性或方法时,如果在当前对象中找不到,会继续在当前对象的原型对象中查找;如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型);直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回 undefined。这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组建的整个链条就是原型链。拥有相同原型的多个对象,他们的共同特征正是通过这种查找模式体现出来的。
在上面的查找过程, 我们提到了最顶层的原型对象, 这个对象就是Object.prototype,这个对象中保存了最常用的方法,如 toString、valueOf、hasOwnProperty 等,因此我们才能在任何对象中使用这些方法。
点击查看更多

7、 闭包

闭包:
** 当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包.**

闭包是一个环境,具体指的就是外部函数–高阶函数 closure
闭包的三个特性
1:函数套函数
2:内部函数可以直接访问外部函数的内部变量或参数
3:变量或参数不会被垃圾回收机制回收 GC

闭包的优点:
1:变量长期驻扎在内存中
2:避免全局变量的污染
3:私有成员的存在

闭包的缺点
常驻内存 增大内存的使用量 使用不当会造成内存的泄露. 闭包的两种写法:

1function a () {
    
     var num=1;
function b () {
    
     alert(num)

}
return b;//把函数 b 返回给函数 a;
}
alert(a())//弹出函数 a, 值是函数 b;
2function a () {
    
     var num=1;
return function b () {
    
    //把函数 b 返回给函数 a; alert(num=num+2)
}
}
alert(a())//弹出函数 a, 值是函数 b;
调用方式:
//1:直接调用
a()()//内部函数的执行

//2:通过赋值在调用var f = a();
f()

查看更多

8、 js 继承

Es5中的继承有:

原型继承: 父类的实例作为子类的原型

构造函数继承 :在子类中使用call方法调用父类的方法并将父类的this改成子类的this
不能继承原型属性/方法,只能继承父类的实例属性和方法

组合继承 :既能调用父类的实例属性又能调用父类的原型属性
由于调用了两次父类,所以产生了两份实例

函数可以复用

Es6有class继承
class就相当于Es5中的构造函数
class中定义方法是前后不能加function,全部都定义在class的prototype属性中
class中只能定义方法不能定义对象变量等
class默认是严格模式
在子类中调用extends方法 可以调用父类的属性,用eat调用父类的方法

9、 什么是深拷贝,浅拷贝,如何实现

在这里插入图片描述

深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。
深拷贝
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响, 对一个对象的修改并不会影响另一个对象。
浅拷贝
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。
可 以 使 用 for in 、 Object.assign 、 扩 展 运 算 符 … 、Array.prototype.slice()、Array.prototype.concat() 、递归等递归函数实现深拷贝

10、 事件冒泡,事件捕获

什么是事件?
事件是文档和浏览器窗口中发生的特定的交互瞬间。 事件是 javascript 应用跳动的心脏,也是把所有东西黏在一起的胶水,当我们与浏览器中 web 页面进行某些类型的交互时,事件就发生了。
事件可能是用户在某些内容上的点击,鼠标经过某个特定元素或按下键盘上的某些按键,事件还可能是 web 浏览器中发生的事情,比如说某个 web 页面加载完成,或者是用户滚动窗口或改变窗口大小。
什么是事件流?
事件流描述的是从页面中接受事件的顺序,但有意思的是,微软(IE)和网景(Netscape)开发团队居然提出了两个截然相反的事件流概念,IE 的事件流是事件冒泡流(event bubbling), 而 Netscape 的事件流是事件捕获流(event capturing)。

事件冒泡和事件捕获的概念:
事件冒泡和事件捕获是描述事件触发事件时序问题的术语,事件捕获指的是从 document 到触发事件的那个节点,也就是说自上而下的去触发事件,相反的, 事件冒泡是自下而上的去触发事件,绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获,true 为事件捕获,false 为事件冒泡, jQuery 的e.stopPropagation 会阻止冒泡,意思就是到我为止,我的爹和祖宗的事件就不要触发了。

  1. 第一种:事件冒泡
    IE 提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点
    执行顺序: p=>button=>div=>body
    正如上面我们所说的,它会从一个最具体的的元素接收,然后逐级向上传播,
    p=>button=>div=>body 事件冒泡可以形象地比喻为把一颗石头投入水中, 泡泡会一直从水底冒出水面,也就是说从小到大开始传播。
  2. 第二种:事件捕获
    网景公司提出的事件流叫事件捕获流。
    事件捕获流的思想是不太具体的 DOM 节点应该更早接收到事件,而最具体的节点应该最后接收到事件,针对上面同样的例子,点击按钮,那么此时 click 事件会按照这样传播:(下面我们就借用 addEventListener 的第三个参数来模拟事件捕获流),也就是上面的例子就会倒过来。

正如我们看到的,和冒泡流万全相反,从最不具体的元素接收到最具体的元素接收事件 body=>div=>button=>p

11、 h5 和css3 的新特性

h5 每个人有每个人的理解,我的理解呢h5 呢并不是新增一些标签和样式更多的是里面新增的一些功能例如重力感应,他可以让我们感知当前手机的状态,可以帮助我们完成手机摇一摇,监听当前我们步数,而且 h5 中为了提高页面性能,页面元素的变大,不在是元素本身的大小变化,而是一种视觉上的效果,从而减少了 dom 操作,防止了页面的重绘

点击查看更多

12、 何为受控组件(controlled component)?

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

13、 Axios 拦截做过哪些

Axios 拦截分为请求拦截和响应拦截,
**请求拦截就是在你请求的时候会进行触发!**只要是你发送一个 axios 请求就会触发!所以我们主要用它做我们的loading 加载和数据的权限验证,包括我们所有的数据预加载也可以实现,
响应拦截主要是我们在 loading 加载,和做所有数据加载需要整体的结束,这个时候的结束就需要在数据马上发给前端的时候进行隐藏和结束,包括我们的请求头的设置,后端数据已经发送过来的时候,我们为了确保请求头的传递就必须在看看header 里面是否有你需要的请求,如果有的话,再次进行设置!当然用 axios 拦截也可以配置公用地址,以及对于跨域问题解决,这个就是用 axios 拦截实现的功能。

14、 sessionStorage localStorage cookie 的区别

1.localStorage 生命周期是永久,这意味着除非用户显示在浏览器提供的UI 上清除 localStorage 信息,否则这些信息将永远存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。
2.sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除。存 放数据大小为一般为 5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。源生接口可以接受,亦可再次封装来对 Object 和 Array 有更好的支持。

作用域不同
不同浏览器无法共享 localStorage 或 sessionStorage 中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享 sessionStorage 的信息。这里需要注意的是,页面及标
3.cookie 的优点:具有极高的扩展性和可用性
1.通过良好的编程,控制保存在 cookie 中的 session 对象的大小。
2.通过加密和安全传输技术,减少 cookie 被破解的可能性。
3.只有在 cookie 中存放不敏感的数据,即使被盗取也不会有很大的损失。
4.控制 cookie 的生命期,使之不会永远有效。这样的话偷盗者很可能拿到的就是一个过期的 cookie。
4.cookie 的缺点:
1.cookie 的长度和数量的限制。每个 domain 最多只能有 20 条 cookie,每个cookie 长度不能超过 4KB。否则会被截掉。
2.安全性问题。如果 cookie 被人拦掉了,那个人就可以获取到所有 session
信息。加密的话也不起什么作用。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务端保存一个计数器。若吧计数器保存在客户端,则起不到什么作用。 localStorage、sessionStorage、Cookie 共同点:都是保存在浏览器端,且同
源的。

15、 图片懒加载实现原理(src赋值原理)

一.什么是懒加载?

懒加载突出一个“懒”字,懒就是拖延迟的意思,所以“懒加载”说白了就是延迟加载,比如我们加载一个页面,这个页面很长很长,长到我们的浏览器可视区域装不下,那么懒加载就是

优先加载可视区域的内容,其他部分等进入了可视区域在加载。

二.为什么要懒加载?

网页性能优化,极大的提升用户体验和服减轻服务器压力

图片一直是影响网页性能的主要元凶,现在一张图片超过几兆已经是很经常的事了。如果每次进入页面就请求所有的图片资源,那么可能等图片加载出来用户也早就走了。所以,我们需要懒加载,进入页面的时候,只请求可视区域的图片资源。
总结出来就两个点:

1.全部加载的话会影响用户体验
2.浪费用户的流量,有些用户并不像全部看完,全部加载会耗费大量流量。
3.懒加载的实现原理?
由于网页中占用资源较多的一般是图片,所以我们一般实施懒加载都是对图片资源而言的,所以这里的实现原理主要是针对图片。
大家都知道,一张图片就是一个标签,而图片的来源主要是 src 属性。浏览器是否发起请求就是根据是否有 src 属性决定的。
既然这样,那么我们就要对标签的 src 属性下手了,在没进入可视区域的时候,我们先不给这个标签赋 src 属性,这样岂不是浏览器就不会发送请求了。

查看更多
拓展:预加载和懒加载的区别

16、 瀑布流原理

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式
视觉表现为参差不齐的多栏布局,最早采用此布局的是网站是 Pinterest, 后逐渐在国内流行即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置。

当第一排排满足够多的等宽图片时,自然而然的考虑到之后
放置的图片会往下面排放。

我们通过瀑布流算法实验得到,后面紧跟的第六张图片的位置应该是这个位置。
因为放置它之前,这一列的高度为所有列中最小,所以会放置在这个地方。所以我们知道了,如果再继续放置下去

通过瀑布流算法实验得出位置正确。
看懂这个图示应该就能理解了瀑布流的原理算法。
总结瀑布流布局原理:
瀑布流的实现原理就是通过比较每一列的高度,如果这一列高度低的话就在这一列进行添加,如果可视区距离和滚动距离想加的话比你当前页面的高度还要高的时候,页面就开再次加载多个,这个主要也是页面布局,如果你的布局实现的不好的话!也会出现问题,首先每一列的高度,都是需要自适应的,不能设置高通过每一块内容将每一列撑起来,还有一个问题就是,滑动底部,根据每个电脑的不同,所以他每个人,获取的高度是不同而且有的时候,页面的整体高度和页面可视区高度加上滚动高度差 1px 这个时候就需要我们提前加载,不然滑动到底部也加载不出来!

17、 meta 标签内属性及详解

点击查看更多

18、 解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
解构赋值,左右结构必须一样,使用左边定义的值,快速的取出数据中对应的数据值,而且 定义和赋值必须放到一起,不然的话就会报错,取不出来数据值,而且左边也必须是一个 js 存在数据结构不然的话也会报错,解构赋值的主要作用还是,快速的让我们在数据中抓取出我们想要的数据。

19、对BFC规范(块级格式化上下文:block formatting context)的理解?

BFC规定了内部的Block Box如何布局。
定位方案:
内部的Box会在垂直方向上一个接一个放置。
Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠。
每个元素的margin box 的左边,与包含块border box的左边相接触。
BFC的区域不会与float box重叠。
BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
计算BFC的高度时,浮动元素也会参与计算。

满足下列条件之一就可触发BFC:
根元素,即html
float的值不为none(默认)
overflow的值不为visible(默认)
display的值为inline-block、table-cell、table-caption
position的值为absolute或fixed

20、 async/await

Async 和 await 是一种同步的写法,但还是异步的操作
asyns 可以把普通的函数改成异步函数,调用都是一样的
异步的asyns函数返回的是一个promise对象
async配合await使用(阻塞式)是异步方法但它是一个阻塞的异步方法

他们的优点
方便联机调用,依次发生的场景
同步代码编写方式,从上到下执行
多个参数传递,跟promise不一样,可以当做普通变量来处理,也可以当做块级变量,想怎么用就怎么用,想定义几个变量就定义几个
同步代码和异步代码可以一起编写,不用纠结同步和异步的区别,把异步封装成一个promise对象放在await后面
是对promise的优化,
我的主要应用是在数据的接收,和异步问题的处理,主要是还是解决不同执行时机下的异步问题!

21、 es6 有哪些拓展

1.新增了块级作用域(let,const)
2.提供了定义类的语法糖(class)
3.新增了一种基本数据类型(Symbol)
4.新增了变量的解构赋值
5.函数参数允许设置默认值,引入了 rest 参数,新增了箭头函数
6.数组新增了一些 API,如 isArray / from / of 方法;数组实例新增了
entries(),keys() 和 values() 等方法
7.对象和数组新增了扩展运算符…
8.ES6 新增了模块化(import/export)
9.ES6 新增了 Set 和 Map 数据结构
10.ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例
11.ES6 新增了生成器(Generator)和遍历器(Iterator)

22、 已删除

23、 请写出在vue 中使用promise 封装项目api 接口的思路?

axios 封装了原生的 XHR,让我们发送请求更为简单,但假设在一个成百上千个 vue 文件的项目中,我们每一个 vue 文件都要写 axios.get()或 axios.post() 岂不是很麻烦?后期的维护也不方便,所以我们要对 axios 进行进一步的封装。

1.构赋 vue-cli 项目的目录如上,我们在原有的目录基础上新建 api 与 utils
文件夹,utils 里新建 request.js 文件,request.js 代码如下:
在 request.js 中做了三件事(拦截器
1.创建 axios,设置 baseURL 与超时时间
2.拦截请求
3.拦截响应

4.路由拦截

24.深度监听(handler固定值 deep深度监听 immediate立即执行)

data:{
    
    

     return(){
    
    

      form:{
    
    id:1,name:marry}

        }

},

watch:{
    
    

//1.监听对象

     form:{
    
    

     handler(a,b){
    
    

                //代码块   

                }

deep:true   // **默认值是 false,代表是否深度监听**

immediate:true   //**代表在wacth里立即先去执行handler方法**

}//2.监听对象中的一个属性(用字符串)

"form.name":{
    
    

     handler(a,b){
    
    

                //代码块   

                }

deep:true   // **默认值是 false,代表是否深度监听**

immediate:true     //**代表在wacth里立即先去执行handler方法**

}

}

查看更多

25、 promise 是什么?有哪些状态和参数?如何使用?

1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作 promise,帮助我们处理队列
resolve 作用是,将 Promise 对象的状态从**“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject 作用是,将 Promise 对象的状态从
“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise 有三个状态:
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当 promise 状态
发生改变,就会触发 then()里的响应函数处理后续步骤;** promise 状态一经改变,不会再变。
Promise 对象的状态改变,只有两种可能: 从 pending 变为 fulfilled
从 pending 变为 rejected。
这两种情况只要发生,状态就凝固了,不会再变了。
手写异步加载图片

26、 for…in 迭代和 for…of 有什么区别

1、推荐在循环对象属性的时候,使用 for…in,在遍历数组的时候的时候使用for…of。
2、for…in 循环出的是 key,for…of 循环出的是 value
3、注意,for…of 是 ES6 新引入的特性。修复了 ES5 引入的 for…in 的不足
4、for…of 不能循环普通的对象,需要通过和 Object.keys()搭配使用

27、 generator(异步编程、yield、next()、await 、async)

提示:Generator 是一个迭代器生成函数,其返回值是一个迭代器(Iterator),可用于异步调用
比如某个事物只有三种状态(状态 A,状态 B,状态 C),而这三种状态的变化是状态 A =>状态 B =>状态 C =>状态 A ,这就是状态机。Generator 特别适用于处理这种状态机

28、 Ajax 是什么?以及如何创建 Ajax?

1.创建 xhr 核心对象
2.调用 open 准备发送
3.如果是post请求,必须设置 请求头。
4.调用 send 发送请求 (如果不需要参数,就写null)
5.监听 异步回调
备注:如果是post请求,想要传json格式数据。

查看更多

29、mvc和mvvm的区别?(个人总结)

mvc:model模型 view视图 controller控制器

视图请求数据到控制器,控制器向模型获取数据后,模型返回数据到视图渲染

mvvm:model数据 view视图UI viewmodel控制器

两者不同的之处在于后者mvvm在处理返回数据时,不需要在将数据传到控制器到视图渲染,这个时候是同步的(双向数据绑定),一端更新,另一端自动更新

30、什么是跨域,以及jsonp的原理?

1、理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域
2、出于安全考虑,服务器不允许 ajax 跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建 script 标签,使用标签的 src 属性访问 js 文件的形式获取 js 脚本,并且这个 js 脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的jsonp原理。

31、跨域的解决方式有哪些?

答:产生跨域的情况有:不同协议,不同域名,不同端口以及域名和 ip 地址的访问都会产生跨域。

跨域的解决方案目前有三种主流解决方案
是 jsonp
1.jsonp 实现原理:主要是利用动态创建 script 标签请求后端接口地址,然后传递 callback 参数,后端接收 callback,后端经过数据处理,返回 callback 函数调用的形式,callback 中的参数就是 json
优点:浏览器兼容性好,
缺点:只支持 get 请求方式
2.代理(前端代理和后端通常通过 nginx 实现反向代理)
前端代理我在vue 中主要是通过vue 脚手架中的config 中的index 文件来配置的,其中有个 proxyTable 来配置跨域的
前端代理核心实现通过 http-proxy-middleware 插件来实现的,vue2.x 和
vue3.x 脚手架代理跨域实现原理是一样的是 CORS
3.CORS 全称叫跨域资源共享,主要是后台工程师设置后端代码来达到前端跨域请求的
CORS 的原理:CORS 定义一种跨域访问的机制,可以让 AJAX 实现跨域访问。 CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

优点:无需前端工程师设置,只需后端工程师在请求的页面中配置好,并且支持所有请求方式(例如:get,post,put,delete 等)
缺点:浏览器支持有版本要求,如下:
chrome:13+,firefox:3.5+,IE 11+,edge:12+
注:现在主流框架都是用代理和 CORS 跨域实现的

32、 说一下从输入 URL 到页面加载完中间发生了什么?

答:大致过程是这样的:
1.DNS 解析
2.TCP 连接
3.发送 HTTP 请求
4.服务器处理请求并返回需要的数据
5.浏览器解析渲染页面

6.连接结束
注:这里会延伸出问 http 状态码,和三次握手和四次挥手相关问题:
点击查看更多

33、 Vue 中 methods,computed, watch 的区别

1)methods 中都是封装好的函数,无论是否有变化只要触发就会执行适用场景:组件中功能的封装,逻辑处理
2)computed:是 vue 独有的特性计算属性,可以对 data 中的依赖项再重新计算得到一个新值,应用到视图中,和 methods 本质区别是 computed 是可缓存的, 也就是说 computed 中的依赖项没有变化,则 computed 中的值就不会重新计算, 而 methods 中的函数是没有缓存的。
适用场景:假设我们有一个性能开销比较大的计算属性 A,它需要遍历一
个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行某个函数
3)Watch 是监听 data 和计算属性中的新旧变化
适用场景:当需要在数据变化时执行“异步”或“开销较大”的操作时,这个方式是最有用的

34、 prop 验证,和默认值

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级prop 的更新会向下流动到子组件中,反之不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
(1)这个用来传递一个初始值;这个子组件接下来希望将其作为一个本地的数据来使用。 在这种情况下,最好定义一个本地的属性并将这个用作其初始值:

(2)这个以一种原始的值传入且需要进行转换。 在这种情况下,最好使用这个的值来定义一个计算属性

35、 vue 双向数据绑定原理

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

36、 vue 组件父子,子父,兄弟通信

第一种:父传子:主要通过 props 来实现的
具体实现:父组件通过 import 引入子组件,并注册,在子组件标签上添加要传递的属性,子组件通过 props 接收,接收有两种形式一是通过数组形式[‘要接收的属性’ ],二是通过对象形式{ }来接收,对象形式可以设置要传递的数据类型和默认值,而数组只是简单的接收

第二种:子传父:主要通过 e m i t 来 实 现 具 体 实 现 : 子 组 件 通 过 通 过 绑 定 事 件 触 发 函 数 , 在 其 中 设 置 t h i s . emit 来实现 具体实现: 子组件通过通过绑定事件触发函数, 在其中设置this. emitthis.emit(‘要派发的自定义事件’,要传递的值),$emit 中有两个参数一是要派发的自定义事件,第二个参数是要传递的值

第三种:兄弟之间传值有两种方法:
方法一:通过 this.$bus o n 实 现 具 体 实 现 : 创 建 一 个 空 的 v u e 并 暴 露 出 去 , 这 个 作 为 公 共 的 b u s , 即 当 作 两 个 组 件 的 桥 梁 , 在 两 个 兄 弟 组 件 中 分 别 引 入 刚 才 创 建 的 b u s , 在 组 件 A 中 通 过 b u s . on实现 具体实现:创建一个空的 vue 并暴露出去,这个作为公共的 bus,即当作两个组件的桥梁,在两个兄弟组件中分别引入刚才创建的bus,在组件 A 中通过 bus. on:vuebus,busAbus.emit(’自定义事件名’,要发送的值)发送数据,在组件 B中通过 bus.$on(‘自定义事件名‘,function(v) { //v 即为要接收的值 })接收数据

方法二:通过 vuex 实现
具体实现:vuex 是一个状态管理工具,主要解决大中型复杂项目的数据共享问题,主要包括 state,actions,mutations,getters 和 modules 5 个要素,主要流程:组件通过 dispatch 到 actions,actions 是异步操作,再 actions中通过 commit 到 mutations,mutations 再通过逻辑操作改变 state,从而同步到组件,更新其数据状态

37、 vue 生命周期

beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问 methods, data, computed 等上的方法和数据。
created ( 创建后)
实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event 事件回调,完成了 data 数据的初始化,el 没有。然而,挂在阶段还没有开始, $el 属性目前不可见,这是一个常用的生命周期, 因为你可以调用 methods 中的方法,改变 data 中的数据,并且修改可以通过 vue 的响应式绑定体现在页面上,,获取 computed 中的计算属性等等,通常我们可
以在这里对实例进行预处理,也有一些童鞋喜欢在这里发 ajax 请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子 beforeRouteEnter 中完成
beforeMount
挂在开始之前被调用,相关的 render 函数首次被调用(虚拟 DOM),实例已完成以下的配置:编译模板,把 data 里面的数据和模板生成 html,完成了 el 和 data 初始化,注意此时还没有挂在 html 到页面上。
mounted
挂在完成,也就是模板中的 HTML 渲染到 HTML 页面中,此时一般可以做一些 ajax 操作,mounted 只会执行一次。
beforeUpdate
在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
updated(更新后)
在由于数据更改导致地虚拟 DOM 重新渲染和打补丁只会调用,调用时,组件 DOM 已经更新,所以可以执行依赖于 DOM 的操作,然后在大多是情况下, 应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
beforeDestrioy (销毁前)
在实例销毁之前调用,实例仍然完全可用,

这一步还可以用 this 来获取实例,
一般在这一步做一些重置的操作,比如清除掉组件中的定时器和监听的dom
事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

38.单向数据流和双向绑定

1.单向数据流
Vue 在不同组件间强制使用单向数据流,父组件可以向子组件传递数据,但是子组件不能直接修改父组件的状态。

2.数据的双向绑定
主要由MVVM框架实现,主要由三部分组成View、ViewModel和Model组成,其中view和model不能直接进行通信,他们通过中间件ViewModel来进行通信。

39、 vue 路由传参数如何实现

ps:主要通过 query 和 params 来实现
query 传参:通过在 router-link 或this. r o u t e r . p u s h ( ) 传 递 u r l 地 址 并 且 拼 接 ? 问 号 传 递 的 参 数 例 如 : r o u r e r − l i n k t o = ” / g o o d s ? i d = 1001 ” , 然 后 在 接 收 的 页 面 通 过 t h i s . router.push()传递 url 地址并且拼接? 问号传递的参数 例如:rourer-link to=”/goods?id=1001”,然后在接收的页面通过 this. router.push()url?rourerlinkto=/goods?id=1001,this.route.query.id 来接收
优点:通用性比较好,刷新数据不会丢失
params 传参:通过在 router-link 或 this. r o u t e r . p u s h ( ) 传 递 u r l 地 址 并 且 拼 接 的 参 数 也 用 / 来 表 示 例 如 : r o u r e r − l i n k t o = ” / g o o d s / 1001 ” , 并 且 在 路 由 页 面 通 过 r o u t e s = [ p a t h : ’ / g o o d s / : i d ’ ] 配 置 , 最 后 在 接 收 的 页 面 通 过 t h i s . router.push()传递 url 地址并且拼接的参数也用/来表示 例如:rourer-link to=”/goods/1001”,并且在路由页面通过 routes=[{path:’/goods/:id’}]配置,最后在接收的页面通过 this. router.push()url/rourerlinkto=/goods/1001,routes=[path:/goods/:id]this.route.params.id来接收
优点:传递数据量在,优雅
缺点:刷新数据不会丢失

40、 路由导航守卫有几种,如何实现

路由钩子函数有三种分别为 :全局守卫 单个路由守卫 组件内部守卫

全局守卫钩子 beforeEach
单个路由守卫 beforeEnter
组件内部守卫 beforeRouteEnter beforeRouteUpdate beforeRouteLeave

to 对象 去哪儿 from 对象 从哪来 next 函数 next()==next(true) 继续执行 不写**next==next(false)**终止执行 **next(path)**跳转

查看更多

41 、 vuex 中 state,getters,mutations,actions,modules,plugins 的用途,和用法

  1. state:存储状态(变量)
  2. getters:对数据获取之前的再次编译,可以理解为 state 的计算属性。我们在组件中使用 $sotre.getters.fun()
  3. mutations : 修 改 状 态 , 并 且 是 同 步 的 。 在 组 件 中 使 用$store.commit(’’,params)。这个和我们组件中的自定义事件类似。
  4. actions:异步操作。在组件中使用是$store.dispath(’’)
  5. modules:store 的子模块,为了开发大型项目,方便状态管理而使用的。这里我们就不解释了,用起来和上面的一样。

42、 vue 中 key 的作用

key 值:用于管理可复用的元素
因为 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做使 Vue 变得非常快,但是这样也不总是符合实际需求。 2.2.0+ 的版本里,当在组件中使用 v-for 时,key 是必须的。”

43、 vue 自定义指令如何使用

【全局指令】
使用 Vue.diretive()来全局注册指令。
【局部指令】
也可以注册局部指令,组件或 Vue 构造函数中接受一个 directives 的选项。

钩子函数。指令定义函数提供了几个钩子函数(可选)。
【bind】
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

【inserted】
被绑定元素插入父节点时调用( 父节点存在即可调用, 不必存在于
document 中)。
【update】
所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新。
【componentUpdated】
所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
【unbind】
只调用一次,指令与元素解绑时调用。钩子函数参数
钩子函数被赋予了以下参数
【el】
指令所绑定的元素,可以用来直接操作 DOM。
【binding】
一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值,例如: v-my-directive=“1 + 1”, value 的值是 2。oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。例如 v-my-directive=“1 + 1” , expression
的值是 “1 + 1”。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。 modifiers: 一个包含修饰符的对象。例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。

44、 vue 常用修饰符

.stop: 阻止点击事件冒泡。等同于 JavaScript 中的 event.stopPropagation()
使用了.stop 后,点击子节点不会捕获到父节点的事件
.prevent 防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播),等同于 JavaScript 中的 event.preventDefault(),prevent 等同于 JavaScript 的 event.preventDefault(),用于取消默认事件。
.capture 与事件冒泡的方向相反,事件捕获由外到内,捕获事件:嵌套两三层父子关系,然后所有都有点击事件,点击子节点,就会触发从外至内父节点-》子节点的点击事件
.self 只会触发自己范围内的事件,不包含子元素
.once 只执行一次,如果我们在@click 事件上添加.once 修饰符,只要点击按钮只会执行一次。
.passive Vue 还对应 addEventListener 中的 passive 选项提供了 .passive
修饰符

45、 keep-alive 的作用

缓存组件页面的状态
1、 在 vue 项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜索的结果列表,这时候就需要用到 vue 的 keep-alive 技术了.
2、 在 router-view 上使用可以缓存该路由组件
3、 有两个参数 include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存

47、 Object.defineProperty()方法有何作用

1、语法 Object.defineProperty(obj, prop, descriptor)
2、定义:Object.defineProperty() 直接在一个对象上定义一个新属性,或者修改现有属性,并返回该对象。
3、参数
obj 要在其上定义属性的对象。
prop 要定义或修改的属性的名称。
descriptor 将被定义或修改的属性描述符。
4、返回值
返回被操作的对象,即返回 obj 参数
5、注意点
1)当把 configurable 值设置为 false 后,就不能修改任何属性了,包括自己本身这个属性
2)想用访问器属性模拟默认行为的话,必须得在里面新顶一个属性,不然的话会造成循环引用
3)可枚举属性对 for/in, Object.keys(), JSON.stringify(), Object.assign() 方法才生效(for/in 是对所有可枚举属性,而其他三种是对自身可枚举属性)

6、用途
1)vue 通过 getter-setter 函数来实现双向绑定
2)俗称属性挂载器
3)专门监听对象数组变化的 Object.observe()(es7)也用到了该方法

48、 什么是虚拟dom,和 diff 算法

1、虚拟 DOM 的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的 DOM 操作。例如,一个 ul 标签下很多个 li 标签,其中只有一个 li 有变化,这种情况下如果使用新的 ul 去替代旧的 ul,因为这些不必要的 DOM 操作而造成了性能上的浪费。
为了避免不必要的DOM 操作,虚拟 DOM 在虚拟节点映射到视图的过程中, 将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行 DOM 操作,从而避免操作其他无需改动的 DOM。
简而言之主要做了两件事:
提供与真实DOM 节点所对应的虚拟节点 vnode 将虚拟节点vnode 和旧虚拟节点 oldVnode 进行对比,然后更新视图
2、diff 算法包括几个步骤:
a.用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
b.当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
c.把所记录的差异应用到所构建的真正的 DOM 树上,视图就更新了

查看更多

49、 vue 中数组中的某个对象的属性发生变化,视图不更新如何解决

问题原因:因为 vue 的检查机制在进行视图更新时无法监测 数组中的某个对象的属性值的变化。解决方案如下
方案一:利用 this.set(this.obj,key,val)
例:this.set(this.obj,‘k1’,‘v1’)

方案二:就利用 Object.assign({},this.obj)创建新对象如果是数组就 Object.assign([],this.obj)
如果是对象就 Object.assign({},this.obj)

50、 vue3.0 与 vue2.0 的区别

1、性能提升
一句话简介:更小巧,更快速;支持摇树优化;支持 Fragments 和跨组件渲染;支持自定义渲染器。
2、API 变动
一句话介绍:除渲染函数 API 和 scoped-slot 语法之外,其余均保持不变或者将通过另外构建一个兼容包 来兼容 2.x。
模板语法的 99% 将保持不变。除了 scoped slot 语法可能会有一些微调之外变动最大的部分将是渲染函数 (render) 中的虚拟 DOM 的格式。
3、重写虚拟 DOM (Virtual DOM Rewrite)
随着虚拟 DOM 重写,减少 运行时(runtime)开销。重写将包括更有效的代码来创建虚拟节点。

51.组件通信

父传递子如何传递
(1)在父组件的子组件标签上绑定一个属性,挂载要传输的变量
(2)在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props:[“属性 名”] props:{属性名:数据类型}
子传递父如何传递
(1)在父组件的子组件标签上自定义一个事件,然后调用需要的方法
(2)在子组件的方法中通过 this.$emit(“事件”)来触发在父组件中定义的事件,数据是以参数的形式进行传递的

兄弟组件如何通信
(1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
(2)在传输数据的一方引入Bus.js 然后通过Bus. e m i t ( “ 事 件 名 ” , " 参 数 " ) 来 派 发 事 件 , 数 据 是 以 emit(“事件名”,"参数")来派发事件,数据是以 emit(,"")emit()的参数形式来传递
(3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on(“事件名”,(data)=>{data是接受的数据})

52.Vue中双向数据绑定是如何实现

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

第一步: 需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

第二步: compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

第三步: Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

第四步: MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

Object.defineProperty(obj, prop, descriptor)
参数:
obj: 必需。目标对象;
prop: 必需。需定义或修改的属性的名字;
descriptor: 必需。目标属性所拥有的特性;

53.keep-alive是什么

keep-alive是Vue提供给我们一个内置组件,他可以用来保存我们路由切换时组件的状态

  1. 全局保存在App.vue中 把routerView保存起来
  2. 部分缓存
    1、router.js中设置要缓存的页面
    {
    path: ‘/child1’,
    name: ‘Child1’,
    component: Child1,
    meta:{
    keepAlive:true
    }
    }
    },
    2、用v-if来显示router-view是否在keep-alive中出现



54.作用域

js中首先有一个最外层的作用域,全局作用域;

js中可以通过函数来创建一个独立作用域称为函数作用域,函数可以嵌套,所以作用域也可以嵌套;

es6中新增了块级作用域(大括号,比如:if{},for(){},while(){}…) es6作用域,只适用于const,let ;

55.继承

Es5中的继承有:

原型继承:父类的实例作为子类的原型

构造函数继承:在子类中使用call方法调用父类的方法并将父类的this改成子类的this

不能继承原型属性/方法,只能继承父类的实例属性和方法

组合继承:既能调用父类的实例属性又能调用父类的原型属性

由于调用了两次父类,所以产生了两份实例

函数可以复用

Es6有class继承
class就相当于Es5中的构造函数

class中定义方法是前后不能加function,全部都定义在class的prototype属性中

class中只能定义方法不能定义对象变量等

class默认是严格模式

在子类中调用extends方法可以调用父类的属性,用eat调用父类的方法

56.深拷贝浅拷贝

浅拷贝只复制指向某个对象的指针,不复制对象本身(引用),新旧对象还是共享同一块内存。
深拷贝会另外创造一个一模一样的对象(拷贝的是全部),新对象跟原对象不共享内存,修改新对象不会改到原对象。

57.let,const,var的区别

是否存在块作用域
var 是不存在块作用域的,let和const有块作用域
是否有变量提升
var有变量提升:
声明之前调用,就会把变量提升到最顶部。 let和const没有变量提升
是否允许重复声明
var允许重复声明 let和const在同一个作用域内不予许重复声明
是否存在暂时性死区
var没有暂时性死区 let和const存在暂时性死区:在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”,
是否可以修改声明的变量
var和let可以修改 ,const不可以,因为const声明的变量是一个常量,一旦定义必须赋值且不可改变

58.Vue 自定义组件及组件封装

自定义组件分为三步
引用组件 注册组件 使用组件
Vue组件封装(以封装一个button组件为例)
1/在components文件内创建一个button文件,文件内创建一个index.vue文件,在index.vue文件内写的是原型(包含组件的名字,应用的最底层的HTML标签,分别根据什么条件显示什么功能),同时该文件导出的数据为一个对象。
2/在button文件下建立一个index.js文件,文件内对新构建组件的名字进行注册。
3/ 与button文件同级建立一个index.js文件,对组件进行注册,同时也注册进install中,在导出时,不仅要引出全局的,而且单个的也要引出,便于局部或全局引用。
4/要在main.js中进行引用
5/到这里,组件便是封装完成了,在App.vue中可以进行使用了

59.vue项目打包

一、修改请求静态资源的路径
打开config下的index.js文件,修改assetsPublicPath的值,从‘/’改为‘./’。即从根路径改为相对路径。

build: {
    
    
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',
 }

二、修改本地图片的路径
打开build下的utils.js文件,增加 publicPath:’…/…/’

if (options.extract) {
    
    
  return ExtractTextPlugin.extract({
    
    
    use: loaders,
    fallback: 'vue-style-loader',
    publicPath:'../../'
  })
} else {
    
    
  return ['vue-style-loader'].concat(loaders)
}

三、在终端运行npm run build。

60.防抖和节流

防抖: 触发高频事件后 定时器内函数只会执行一次,如果定时器内高频事件再次被触发,则重新计算时间
场景:
按钮提交场景:防止多次提交按钮,只执行最后提交的一次。

节流 :高频事件触发,在定时器内只会执行一次,所以节流会稀释函数的执行效率。
1.拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动

2.缩放场景:监控浏览器 resize

3.动画场景:避免短时间内多次触发动画引起性能问题

61.数组去重

indexOf

 
function newArr(array){
    
     
    //一个新的数组 
    var arrs = []; 
    //遍历当前数组 
    for(var i = 0; i < array.length; i++){
    
     
        //如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面 
        if (arrs.indexOf(array[i]) == -1){
    
     
            arrs.push(array[i])
        }; 
    } 
    return arrs; 
}
 
var arr = [1,1,2,5,5,6,8,9,8];
 
console.log(newArr(arr))

Set

function newArr(arr){
    
    
    return Array.from(new Set(arr))
}
 
var arr = [1,1,2,9,6,9,6,3,1,4,5];
 
console.log(newArr(arr))

利用递归去重

62.Git指令

git init 初始化git仓库
git status 查看文件状态
git add 文件列表 追踪文件
git commit -m 提交信息 向仓库中提交代码
git log 查看提交记录
覆盖工作目录中的文件: git checkout --文件名
将文件从暂存区中删除: git r m --cached 文件名

git branch 查看分支

git branch 分支名称 创建分支

git checkout 分支名称 切换分支

git merge 来源分支 合并分支 (必须在master分支上才能合并d)

git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)

将本地仓库推送到远程仓库: git push 项目链接

Git 添加远程仓库origin (origin是仓库别名): git remote add 仓库名 项目链接

git push origin master
git push -u origin master

-u 将推送地址和分支保存,下次推送输入git push即可

63.什么是盒子模型?

在我们HTML页面中,每一个元素都可以被看作一个盒子,而这个盒子由:内容区(content)、填充区(padding)、边框区(border)、外边界区(margin)四部分组成。

64.什么是内存泄漏

程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。
对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

或者这么回答,如下:
简单地说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。

65.数组常用的方法

1. join (将数组用 - 符号连接起来,原数组不受影响)
2. split (指定的分隔符,将字符串分割成数组。)
3.push 该方法可以在数组的最后面,添加一个或者多个元素结构: arr.push(值) 返回值:返回的是添加元素后数组的长度.
4.pop 该方法可以在数组的最后面,删除一个元素 结构: arr.pop(值)返回值:返回的是刚才删除的元素.
5. unshift 该方法可以在数组的最前面,添加一个或者几个元素 结构: arr.unshift(值) 返回值: 返回的是添加元素后数组的长度
6.shift 该方法可以在数组的最前面,添加一个元素 结构: arr.shift(值)
7. reverse 翻转数组 结构:arr.reserse()
8. sort 该方法可以对数组进行排序.

let arr = [1,3,5,2,4,23,122,34];
//没有参数:**时按照首字符的先后排序**================================================
arr.sort()//arr=[1,122,2,23,3,34,4,5];
//**有参数**================================================
arr.sort(function(a,b){
    
    
	return a-b;//从小到大排序
	return b-a;//从大到小排序
})

点击查看更多

66.js生成随机数/数组

点击查看更多

67.javascript math中常用的数学方法

JS 中常用的数学方法:

/*绝对值运算*/
    Math.abs(-5);   //5
    Math.abs(5);   //5
 
    /*四舍五入运算*/
    Math.round(2.6);   //3
    Math.round(2.4);   //2
 
    /*向上取整运算*/
    Math.ceil(1.1);   //2
    Math.ceil(1.9);   //2
 
    /*向下取整运算*/
    Math.floor(1.1);    //1
    Math.floor(1.9);    //1
    
    /*多个数取最大值,可有多个参数*/
    Math.max(x1,x2,x3,...);
    Math.max(-2,5);      //5
    Math.max(2,-5,8);    //8
 
    /*多个数取最小值,可有多个参数*/
    Math.min(x1,x2,x3,...);
    Math.min(-2,5);     //-2
    Math.min(2,-5,8);   //-5
 
    /*获取随机数大于等于0小于1*/
    Math.random();      //随机产生[0,1)的数
    
    /*Math的其他方法*/
    Math.cos(x);        //参数是以弧度为单位的数值,返回余弦值
    Math.exp(x);        //参数是数值,返回e的x次方
    Math.log(x);        //参数是数值,返回lnx
    Math.sqrt(x);       //参数是数值,返回平方根
    Math.pow(x,y);      //参数一次是基数、指数,返回x的y次方
 

猜你喜欢

转载自blog.csdn.net/qq_37430247/article/details/111667103