Vue must know knowledge points

1. Lazy loading of vue-router routes

vue异步组件 
	{ path: '/home', name: 'home', component: resolve => require(['@/components/home'],resolve) },



es提案的import()	
const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
	{ path: '/', name: 'HelloWorld', component: () => import("@/Home ")  }



webpack的require,ensure()
	const list = r => require.ensure([], () => r(require('../components/list/list')), 'list');


2. Vue parent-child component life cycle execution sequence

加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

3. css preprocessor

为什么要使用Sass、Less
css只是单纯的属性描述,它并不具有变量、条件语句等,这就导致了它难组织和维护。
Less与Sass的特性
(1)混合:将一个定义好的classA引入到另一个classB中,从而简单实现classB继承了classA的所有属性
(2)嵌套:class中嵌套class,从而减少重复的代码
(3)运算:可以在css中使用数学计算
(4)作用域:可以局部修改样式
(5)js表达式:在css样式中使用js表达式赋值 

4. js data type judgment

(1)  typeof 使用typeof来判断null和引用类型 返回的结果都是 'object' NaN的数据类型是number
(2) instanceof  用来判断A是否为B的实例,A instanceof B,如果A是B的实例,返回true否则返回false。instanceof检测的是原型。可以看出[] 的原型指向Array.prototype,间接指向Object.prototype。instanceof只能判断两个对象之间是否属于实例关系,不能判断一个对象属于哪种类型。
(3) constructor  无法判断null和undefined
(4) Object.prototype.toString.call();必须要用object上的tostring,array上的toString方法可能被重写
(5) 判断NaN ES6引入了 Number.isNaN()

5. The process of DNS resolving URL

  浏览器与服务器交互
    1. 首先浏览器利用tcp协议通过三次握手和服务器建立连接
    2. 浏览器根据解析到的IP地址和端口号发起http的get请求
    3. 服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
    4. 若状态码为200显示响应成功,浏览器接收到返回的html页面之后,开始进行页面的渲染
 浏览器页面渲染过程
    1. 浏览器根据深度遍历的方式把html节点遍历成dom树
    2. 将css解析成CSSDOM树
    3. 将dom树和CSSDOM树构造成render树
    4. js根据得到的render树,计算所有节点在屏幕中的位置,进行布局(回流)
    5. 遍历render树并调用硬件API绘制所有节点(重绘)

6. Redraw and reflow

重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI 层面的重新像素绘制,因此损耗较少。
常见的重绘操作有: 改变元素颜色  改变元素背景色 
回流(reflow):又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。常见的回流操作有:页面初次渲染  浏览器窗口大小改变 元素尺寸/位置/内容发生改变 元素字体大小变化 添加或者删除可见的 DOM 元素
激活 CSS 伪类(:hover……) 
重点:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。

7. vue command

v-model是进行动态双向数据绑定
v-bind(缩写为 : )用于绑定数据和元素属性
v-on(缩写为@) 【事件监听】
v-show
v-if是动态的向DOM树内添加或者删除DOM元素,v-show是通过设置DOM元素的display	样式属性控制显隐。
v-if  
v-for不能和v-if一起使用,v-for的优先级更高,v-for和v-show一起使用  
	将v-if放置容器元素上去判断
	将数组用computed计算出来


	computed:{
		activeUser:function(){
			return this.users.filter(function(user){
				return user.isActive
			})
		}
	}
v-text
v-html
v-cloak 防止vue.js没有加载进来的时候,页面显示{
   
   {}}
v-once 只渲染一次数据
prevent:阻止默认事件(常用);
stop:阻止事件冒泡(常用);
v-directive('name',inserted:{function(el,)})自定义指令 该函数接收两个参数,第一个参数为指令名称,在元素中通过 " v-		名称 " 绑定元素,第二个参数为对绑定元素进行处理的钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
          	* bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
            * inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
            * update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后      的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
      * componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
 	  * unbind:只调用一次,指令与元素解绑时调用。
 	  
 	  参数:
      * el:指令所绑定的元素,可以用来直接操作 DOM。
      *  binding:一个对象,包含以下 property:
      *  name:指令名,不包括 v- 前缀。
      *  value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
      *  oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
     *  expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
    *  arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
    *  modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
    *  vnode:Vue 编译生成的虚拟节点。
    *  oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

8. Navigation Guard

全局守卫。router.beforeEach  beforeResolve 全局后置钩子 router.afterEach 不用有next
路由独享守卫。beforeEnter
组件内守卫 beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave
beforeRouteEnter守卫内访问不到组件的实例,也就是this为undefined,也就是他在beforeCreate生命周期前触发。在这个钩子函数中,可以通过传一个回调给 next来访问组件实例。调用next并在回调中通过 vm访问组件实例进行赋值等操作,(next中函数的调用在mounted之后:为了确保能对组件实例的完整访问)。

 beforeRouteEnter (to, from, next) {
 // 这里还无法访问到组件实例,this === undefined
  next( vm => {
    // 通过 `vm` 访问组件实例
  })
}

9. Gantt chart Fullcalendar

10. provide/inject

只能从祖先传递给后代,但是可以通过在App.vue绑定provide,所有的子组件就都能注入inject,从而达到全局传递。

	provide(){
	   return{
	      foo:'halo'
	   }
 	}
     
   //接收
   inject:['foo'],

11. em rem px

一、区别:
1. px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
2. em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定死了的,更适用于响应式布局。
3. em是相对于其父元素来设置字体大小的,一般都是以<body>的“font-size”为基准。这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个参考值。
总之em相对于父元素,rem相对于根元素。
em实例:
 子元素字体大小的em是相对于父元素字体大小
 元素的width/height/padding/margin用em的话是相对于该元素的font-size
 任何浏览器默认字体大小都是16px,所有未经调整的浏览器都符合1em=16px 
举例:
 比如父元素font-size:12px;
 自身元素如果写成:font-size:2em;则自身元素用px表示就是24px(相对父元素字体大小);
 但是自身元素设置:width:2 em,那么自身元素用px表示就是48px(相对自身字体大小);


<div>
    父元素div
    <p>
       子元素p
        <span>孙元素span</span>
    </p>
</div>
 
div {
       font-size: 40px;
       width: 7.5em; /* 300px */
       height: 7.5em;
       border: solid 2px black;
	}
p 	{
       font-size: 0.5em; /* 20px */
       width: 7.5em; /* 150px */
       height: 7.5em;
       border: solid 2px blue ;
       color: blue;
  	 }
span {
       font-size: 0.5em;
       width: 7em;
       height: 6em;
       border: solid 1px red;
       display: block;
       color: red;
   	} 
rem实例:
rem是全部的长度都相对于根元素(<html>元素)。通常做法是给html元素设置一个字体大小,然后其他元素的长度单位就为rem。
比如根元素(html)设置font-size=12px; 非根元素设置width:2rem;则换成px表示就是24px;
如果根元素设置成font-size=1rem;则根元素换成px就是相对于初始字体大小,一般是12px;

<div>
    父元素div
    <p>
       子元素p
        <span>孙元素span</span>
    </p>
</div> 
html {
       font-size: 10px;
     }
div  {
        font-size: 4rem; /* 40px */
        width: 20rem;  /* 200px */
        height: 20rem;
        border: solid 2px black;
     }
p    {
        font-size: 2rem; /* 20px */
        width: 10rem;
        height: 10rem;
        border: solid 1px blue;
        color:blue ;
     }
span {
        font-size: 1.5rem;
        width: 7rem;
        height: 6rem;
        border: solid 2px red;
        display: block;
        color: red;
     } 
区别
1、rem 和 em 单位是由浏览器基于你的设计中的字体大小计算得到的像素值。
2、em 单位基于使用他们的元素的字体大小。
3、rem 单位基于 html 元素的字体大小。
4、em 单位可能受任何继承的父元素字体大小影响
5、rem 单位可以从浏览器字体设置中继承字体大小。
6、使用 em 单位应根据组件的字体大小而不是根元素的字体大小。
7、在不需要使用em单位,并且需要根据浏览器的字体大小设置缩放的情况下使用rem。
8、使用rem单位,除非你确定你需要 em 单位,包括对字体大小。
9、媒体查询中使用 rem 单位
10、不要在多列布局中使用 em 或 rem 改用 %。
11、不要使用 em 或 rem,如果缩放会不可避免地导致要打破布局元素。

12. H5 new features

 1.拖拽释放drag和drop
 2.语义化标签
 	普通标签不利于SEO搜索引擎对页面内容的抓取 文档结构定义不明确
    header — 页眉
    main — 主体
    nav — 导航
    article — 独立的内容
    section — 一个区域,跟div的功能和语义是一样的
    aside — 辅助信息的内容
    footer — 页脚
    figure — 描述图像或视频
    figuretion — 描述图像或视频的标题部分
    hgroup — 标题组合 
 3.音频视频 audio video
 4.画布 canvas
 5.地理Geolacation API
 6.localstorage和sessionstorage
 7.表单控件 date time email
 8.新技术websocket

13. New features of css3

过渡属性  transition: 要改变的属性,花费时间,效果曲线(默认ease),延迟时间(默认0)
动画属性 animation:动画名称,一个周期花费时间,运动曲线(默认ease),动画延迟(默认0),播放次数(默认1),是否反向播放动画(默认normal),是否暂停动画(默认running)
圆角属性 
引入了rgba
盒子阴影  box-shadow:
transform(旋转) transform:rotate(7deg);
box-sizing: content-box;//宽度和高度分别应用到元素的内容框。在宽度和高度之外绘制元素的内边距和边框。 
box-sizing: border-box;// 为元素设定的宽度和高度决定了元素的边框盒。就是说,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。通过从已设定的宽度和高度分别减去边框和内边距才能得到内容的宽度和高度。 
box-sizing: inherit;// 规定应从父元素继承 box-sizing 属性的值。 
即box-sizing属性可以指定盒子模型种类,content-box指定盒子模型为W3C(标准盒模型),border-box为IE盒子模型(怪异盒模型)。 

14. bfc

01.什么是BFC BFC是指浏览器中创建了一个独立的渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。
02.BFC的特点 具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
03.BFC布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠,而是紧贴浮动元素。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算 
04.哪些元素会产生BFC
1、根元素
2、float属性不为none
3、position为absolute或fixed
4、 display为inline-block, table-cell, table-caption, flex, inline-flex
5、 overflow不为visible 
(1)清除盒子垂直方向上外边距合并——盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠。
解决方法:
根据属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠的性质,可以给其中一个盒子再包裹一个盒子父元素,并触发其BFC功能(例如添加overflow:hidden;)这样垂直方向的两个盒子就不在同一个BFC中了,因此也不会发生垂直外边距合并的问题了。
(2)在子元素设置成浮动元素的时候,会产生父元素高度塌陷的问题。
解决方法:
给父元素设置overflow:hidden;的时候会产生BFC
由于在计算BFC高度时,自然也会检测浮动的子盒子高度。所以当子盒子有高度但是浮动的时候,通过激发父盒子的BFC功能,会产生清除浮动的效果。 

15. promise and async/await

都是解决异步编程的一种方式,但是async/await使得异步代码看起来像同步代码。
函数前面多了一个async关键字。await关键字只能用于async定于的函数内。async函数会隐式地返回一个Promise,该promise的resolve值就是return的值。
为什么async/await更好?
使用async函数可以让代码简洁很多,不需要像Promise一样需要then,不需要写匿名函数处理Promise的resolve的值,也不需要定义多余的data变量,还避免
promise
    1、主要用于异步计算
    2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
    3、可以在对象之间传递和操作promise,帮助我们处理队列
    promise有三个状态:
        1、pending[待定]初始状态
        2、fulfilled[实现]操作成功
        3、rejected[被否决]操作失败
    当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
        promise状态一经改变,不会再变 

16. Arrow functions

不能用于构造函数,不能使用new
在普通函数中,this总是指向调用它的对象,如果用作构造函数,this指向创建的对象实例。
箭头函数本身不创建this 箭头函数可以访问到上下文中的this,所以this的指向不同。我们只需要看定义  该箭头函数时,该箭头函数父级的 this 即可
箭头函数不具有prototype原型对象
箭头函数没有super方法

17. vuex data persistence

	1.npm install vuex-persist -s 
		    import Vue from 'vue'
			import Vuex from 'vuex'
			import VuexPersistence from 'vuex-persist' 
			Vue.use(Vuex) 
			export default new Vuex.Store({
				  state: {
				    data: {}
				  },
				  mutations: {
				    saveData(state, obj){
				      state.data = obj;
				    }
				  },
				  plugins: [new VuexPersistence().plugin]
			}) 
	2.npm i vuex-persistedstate 
			import createPersistedState from 'vuex-persistedstate'  
			plugins: [createPersistedState()] 

18. The difference and function of break and continue

用于for循环
break用于完全结束一个循环,跳出循环体执行循环后面的语句。
continue是跳过当次循环中剩下的语句,执行下一次循环。
for和forEach的区别
1.forEach()不能使用break和continue这两个关键字,它实现break效果可以通过抛出异常的方式,实现continue的效果可以直接使用return
2.forEach的优势就是,它传入一个函数,因此形成了一个作用域,它内部所定义的变量不会像for循环一样污染全局变量
3.forEach()本身无法跳出循环,必须遍历所有的数据才能结束 


		try {
		     list.forEach((item,index)=>{
	           if(item.text === '') {
	               throw new Error('finish');
	             }
		      })
		 } catch (e) {
		 } 

19. href and src

 href用于建立当前页面与引用资源之间的关系(链接);
 而src则会替换当前标签。 遇到href,页面会并行加载后续内容;
而src则不同,浏览器需要加载完毕src的内容才会继续往下执行。
 使用src属性的元素,例如img、iframe、script,如果src路径出现问题的话,
页面的内容会受到影响,用户没有办法看到页面本来应该显示的内容和使用页面应该实现的功能。
使用href属性的元素,例如link、a,如果href路径出现问题的话,
页面不会有很大的影响,对于样式文件来说,只是影响页面的美观度,
而不会影响页面的正常浏览和使用,对于超链接来说,
只是页面无法与其它页面建立链接,对当前页面的影响也不大。

20. axios interceptor

// 请求拦截器
instance.interceptors.request.use(req=>{}, err=>{});
// 响应拦截器
instance.interceptors.reponse.use(req=>{}, err=>{});
请求拦截器
在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;
响应拦截器
同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。 
let instance = axios.create({
    baseURL: 'xxxxx',
    timeout: 1000,  // 超时,401
})

21. Secondary promise encapsulation of axios

 原因在于Promise内部用try catch 来捕获的异常,
而try catch不能捕获异步异常,如果有类似的需求还是需要加一层Promise的

22.axios request parameters

axios({
	   url: "/caihongpi/index", // `url` 是用于请求的服务器地址
	   method: "post", // `method` 是创建请求时使用的方法,如果不写默认get
	   headers: {  }, // `headers` 是即将被发送的自定义请求头,设置token
	   params:{}, //get参数会将请求参数拼接在url上    
	   data:{}, //post会将请求参数放在请求体中      
	   timeout: 1000, //指定请求超时的毫秒数(0 表示无超时时间)      
	   responseType: "json", // `responseType` 表示服务器响应的数据类型,默认是json
	   maxContentLength:1000, //相应内容的最大值
	  })  

23. Why are several array methods refactored in vue?

'push','pop','shift','unshift','splice','sort','reverse'
1.Vue 的响应式是通过 Object.defineProperty() 实现的,
这个 api 没办法监听数组长度的变化,也就没办法监听数组的新增。
2.Vue 无法检测通过数组索引改变数组的操作,
这不是 Object.defineProperty() api 的原因,
而是 尤大认为性能消耗与带来的用户体验不成正比。
对数组进行响应式检测会带来很大的性能消耗,因为数组项可能会大,比如1000条、10000条。
所以为了更友好的操作数组并触发响应式检测,Vue 重写了对数组引起副作用(改变原数组)的方法。 

24. Place the html footer at the bottom of the page

需求:有时候,当页面内容较短,撑不开浏览器高度,
但是又希望footer能在窗口最低端。 
思路:footer的父层的最小高度是100%,
footer设置成相对于父层位置绝对(absolute)置底(bottom:0),父层内要预留footer的高度。

25. Why data is a function

1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。

2.vue组件中的data数据都应该是相互隔离,互不影响的,
组件每复用一次,data数据就应该被复制一次,之后,
当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,
就需要通过data函数返回一个对象作为组件的状态 

3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,
这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,
类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
 
4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,
由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。 

26.Manage system permissions dynamic routing

let route=[
	{
	  path: '/pageA',
	  name: 'pageA',
	  component: pageA,
	},
	{
	  path: '/pageB',
	  name: 'pageB',
	  component: pageB,
	},
	{
	  path: '/pageC',
	  name: 'pageC',
	  component: pageC,
	}
]
let commonUser=['pageA','pageB']
let commonUserRoute=route.filter(function(page){
    return commonUser.includes(page.name)
}) 
router.addRoutes(commonUserRoute);


//结果
// (2) [{…}, {…}]
// 0: {path: "/pageA", name: "pageA", component: pageA}
// 1: {path: "/pageB", name: "pageB", component: pageB}
// length: 2 

27.Slot

在 Vue 中,插槽是个很强大的功能,它可以使封装的组件灵活性增强很多,
比如你在封装一个组件时使用了插槽,那在父组件调用时,这里的内容就可以由父组件自由定义,
而无需在封装组件时苦想如何覆盖各种使用场景。

28.eventloop event loop

JS 主线程不断的循环往复的从任务队列中读取任务,执⾏任务,
这种运⾏机制称为事件循环(event loop)

浏览器的事件循环(event loop)中分成宏任务和微任务。
JS 中任务分成同步任务和异步任务。

宏任务
JS 中主栈执⾏的⼤多数的任务,例如:定时器,事件绑定,ajax,回调函数,node中fs操作模块等

微任务
promise, async/await, process.nextTick  

为什么要引⼊微任务,只有宏任务可以吗?
微任务的引⼊是为了解决异步回调的问题,假设只有宏任务,
那么每⼀个宏任务执⾏完后回调函数也放⼊宏任务队列,这
样会造成队列多长,回调的时间变长,这样会造成页⾯的卡顿,所以引⼊了微任务。 
主栈队列就是⼀个宏任务,每⼀个宏任务执⾏完就会执⾏宏任务中的微任务,直到微任务全部都执⾏完,才开始执⾏下⼀个宏任务 

JS 中任务的执⾏顺序优先级是:主栈全局任务(宏任务) > 宏任务中的微任务 > 下⼀个宏任务 

29.git command

git pull
git clone
git add	添加文件到仓库
git status	查看仓库当前的状态,显示有变更的文件。
git diff	比较文件的不同,即暂存区和工作区的差异。
git commit	提交暂存区到本地仓库。
git reset	回退版本。
git rm	删除工作区文件。
git mv	移动或重命名工作区文件。 
git log	查看历史提交记录
git blame <file>	以列表形式查看指定文件的历史修改记录 
git remote	远程仓库操作
git fetch	从远程获取代码库
git pull	下载远程代码并合并
git push	上传远程代码并合并
git branch 	 新建分支/查看分支
git checkout 	  切换分支
git stash save “”	  存储到电脑内存中的某个地方,用于pull时有冲突
git stash apply “stash@{0}”
git merge   A into B	  分支合入

30. The process of entering the URL to display the page:

1.输入URL后,会先进行域名解析。优先查找本地host文件有无对应的IP地址,
没有的话去本地DNS服务器查找,还不行的话,本地DNS服务器会去找根DNS服务器
要一个域服务器的地址进行查询,域服务器将要查询的域名的解析服务器地址返回给本地DNS,
本地DNS去这里查询就OK了。

2.浏览器拿到服务器的IP地址后,会向它发送HTTP请求。
HTTP请求经由一层层的处理、封装、发出之后,最终经由网络到达服务器,
建立TCP/IP连接,服务器接收到请求并开始处理。

3.服务器构建响应,再经由一层层的处理、封装、发出后,到达客户端,浏览器处理请求。

4.浏览器开始渲染页面,解析HTML,构建render树,根据render树的节点和CSS的对应关系,
进行布局,绘制页面。 

31. Prototypes and Prototype Chains

 

 原型对象 : 
在 JavaScript 中,除去一部分内建函数,绝大多数的函数都会包含有一个
叫做 prototype 的属性,指向原型对象, 
基于构造函数创建出来的实例, 都可以共享访问原型对象的属性。  

例如我们的 hasOwnProperty, toString ⽅法等其实是 Obejct 原型对象的方法,它可以被任何对象当做⾃⼰的⽅法来使⽤。 
hasOwnProperty 用于判断, 某个属性, 是不是自己的 (还是原型链上的) 

原型链 : 
在 JavaScript 中,每个对象中都有一个 __proto__ 属性,这个属性指向了当前对象的构造函数的原型。 
对象可以通过自身的 __proto__属性与它的构造函数的原型对象连接起来, 
而因为它的原型对象也有 __proto__,因此这样就串联形成一个链式结构,也就是我们称为的原型链。

32. Simple configuration of echarts

 The following are the settings for setting the chart to adapt to the screen.
Adaptive layout cssrem plug-in and flexible file

33. The process of new an instance object in JS

1.创建一个新的对象obj
2.将对象与构造函数通过原型链连接起来
3.将构造函数中的this绑定到新建的对象obj上
4.判断Person返回值类型,如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象。

const person1 = new Person('Tom',20)
			  ↓ 1.创建一个新的空对象
			 { }
			  ↓ 2.将新对象的[[prototype]]指向为Person.prototye
		{
			__protp__ = Person.prototype
		}	  
			  ↓ 3.将Person构造函数的this设置为新创建的对象,执行Person函数体
		let result = Person.apply(obj)
		{
			__protp__ = Person.prototype;
			name = 'Tom';
			age = 20;
		}
			  ↓ 4.判断构造函数的返回值
		return result instanceof Object? result:obj

The process of handwriting an instance of new

function mynew(Fun ,...args){
  //1.创建一个新的对象
	const obj ={};
  //2.将新对象的[[prototype]]指向为构造函数的prototype
  obj.__proto__ = Fun.prototype;
  //3.将构造函数的this设置为新对象
  let result = Fun.apply(obj,args);
  //4.判断构造函数的返回值
  return result instanceof Object? result:obj;
}

//测试
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function () {
    console.log(this.name)
}
let p = mynew(Person, "huihui", 123)
console.log(p) // Person {name: "huihui", age: 123}
p.say() // huihui

34. Closure

每一个vue组件就是一个闭包
在一个函数a里面有一个函数b  函数b可以调用函数a里面的变量 
但是函数a却调用不了函数b的变量

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

必报的缺点:内存泄漏

如何解决:
    在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;
    就是在JavaScript代码段运行完之时将形成循环引用的JavaScript对象手动设置为空,切断引用

35. Solutions to cross-domain issues

The first:

Cros中间件
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

如果服务器允许跨域,需要在返回的响应头中携带下面信息:
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*,代表任意
Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,
除非这个值是true

注意:
如果跨域请求要想操作cookie,需要满足3个条件:
服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
浏览器发起ajax需要指定withCredentials 为true
响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

The second type

vue-cli脚手架提供的proxyTable解决跨域

vue-cli提供的解决vue开发环境下跨域问题的方法,proxyTable的底层
使用了http-proxy-middleware它是http代理中间件,它依赖node.js,
基本原理是用服务端代理解决浏览器跨域。有时候在开发的时候,
我们请求的后代接口和vue不在同一个域名产生了跨域,而后台服务器并未开启cors,
这个时候需要配置proxyTable解决跨域问题。
proxyTable: {
      // 这里配置 '/api' 就等价于 target , 你在链接里访问 /api === http://localhost:54321
      '/api': {
        target: 'http://localhost:54321/', // 真是服务器的接口地址 // http://localhost:54321/json.data.json,
        secure: true, // 如果是 https ,需要开启这个选项
        changeOrigin: true, // 是否是跨域请求?肯定是啊,不跨域就没有必要配置这个proxyTable了.
        pathRewirte: {
          // 这里是追加链接,比如真是接口里包含了 /api,就需要这样配置.
 
          '/^api': 'api/', 
          // 等价于 
          // step 1  /api = http://localhost:54321/
          // step 2 /^api = /api + api == http://localhost:54321/api
        }
      }
     },

The third kind

Jsonp
1.最早的解决方案,利用script标签可以跨域的原理实现。

2.通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,
实现服务器端向客户端通信

3.由于使用script标签的src属性 因此只支持get方法

The fourth kind

nginx

36. Which properties in css can be inherited

1、字体系列属性
	font:组合字体
	font-family:规定元素的字体系列
	font-weight:设置字体的粗细
	font-size:设置字体的尺寸
	font-style:定义字体的风格
2、文本系列属性
	text-indent:文本缩进
	text-align:文本水平对齐
	line-height:行高
	word-spacing:增加或减少单词间的空白(即字间隔)
	letter-spacing:增加或减少字符间的空白(字符间距)
	text-transform:控制文本大小写
	direction:规定文本的书写方向
	color:文本颜色
3、元素可见性:visibility
4、表格布局属性:
	caption-side、border-collapse、border-spacing、empty-cells、table-layout
5、列表属性:
	list-style-type、list-style-image、list-style-position、list-style
6、光标属性:cursor
不可继承属性
1.display
2.文本属性
	vertical-align:垂直文本对齐
	text-decoration:规定添加到文本的装饰
	text-shadow:文本阴影效果
	white-space:空白符的处理
3.盒子模型属性
	width、height、margin 、margin-top、margin-right、margin-bottom、margin-left、border、border-style、border-top-style、border-right-style、border-bottom-style、border-left-style、border-width、border-top-width、border-right-right、border-bottom-width、border-left-width、border-color、border-top-color、border-right-color、border-bottom-color、border-left-color、border-top、border-right、border-bottom、border-left、padding、padding-top、padding-right、padding-bottom、padding-left
4.背景属性
	background、background-color、background-image、background-repeat、background-position、background-attachment
5.定位属性
	float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index 

37. The difference between pseudo elements and pseudo classes

伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,当用户悬停在指定的元素时,我们可以通过:hover来描述这个元素的状态。虽然它和普通的css类相似,可以为已有的元素添加样式,但是它只有处于dom树无法描述的状态下才能为元素添加样式,所以将其称为伪类。
伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过:before来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。
伪类
1 :link选择未访问的链接
2 :visited选择已访问的链接
3 :hover选择鼠标指针浮动在其上的元素
4 :active选择活动的链接
5 :focus选择获取焦点的输入字段
6 :not一个否定伪类,用于匹配不符合参数选择器的元素
7 :first-child匹配元素的第一个子元素。
8 : last-child匹配元素的最后一个子元素。
9 :first-of-type匹配属于其父元素的首个特定类型的子元素的每个元素。
10 :last-of-type匹配属于其父元素最后一个类型的子元素的每个元素
11 :nth-child根据元素的位置匹配一个或者多个元素,它接受一个an+b形式的参数
12 :nth-last-child 它是从最后一个子元素开始计数的。 
13 :nth-of-type 与nth-child相似,不同之处在于它是只匹配特定类型的元素。
14 :nth-last-type 与nth-of-type相似,不同之处在于它是从最后一个子元素开始计数的。 
15 :only-child 当元素是其父元素中唯一一个子元素时,:only-child匹配该元素。
16 :disabled匹配禁用的表单元素。 
伪元素
1 ::before/:before
	:before在被选元素前插入内容。需要使用content属性来指定要插入的内容。被插入的内容实际上不在文档树中。
2 ::after/:after
	:after在被元素后插入内容,其用法和特性与:before相似。
3 ::first-letter/:first-letter
	:first-letter匹配元素中文本的首字母。被修饰的首字母不在文档树中。
4 ::first-line/:first-line
	:first-line匹配元素中第一行的文本。这个伪元素只能用在块元素中,不能用在内联元素中。
5 ::selection
	::selection匹配用户被用户选中或者处于高亮状态的部分。在火狐浏览器使用时需要添加-moz前缀。该伪元素只支持双冒号的形式。

38. $nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,
获取更新后的 DOM 

一、为什么要有nexttick
举个例子  {
   
   {num}}for(let i=0; i<100000; i++){    num = i} 
如果没有 nextTick 更新机制,那么 num 每次更新值都会触发视图更新
(上面这段代码也就是会更新10万次视图),
有了nextTick机制,只需要更新一次,所以nextTick本质是一种优化策略 

二、使用场景
如果想要在修改数据后立刻得到更新后的DOM结构,可以使用Vue.nextTick() 
  实现原理

The nextTick method mainly uses macro tasks and micro tasks, and defines an asynchronous method. Calling nextTick multiple times will store the method in the queue, and clear the queue through this asynchronous method.

39. The difference between $router and $route

1.$route从当前router跳转对象里面可以获取name、path、query、params等
(<router-link>传的参数由 this.$route.query或者 this.$route.params 接收) 

2 $router为VueRouter实例。想要导航到不同URL,则使用$router.push方法;
返回上一个history也是使用$router.go方法

40. $attrs and $listeners

1.$attrs: 除了组件内props声名了的所有给组件传的值(class,style除外)
当我们需要给多层嵌套父子组件传值,而且杂的时候,可以直接使用它,可以使代码看起来更加简洁
v-bind="$attrs"

2.$listeners: 接收除了带有.native事件修饰符的所有事件监听器 
有一点不同的是:当出现同名的事件时,不会被覆盖,而是都会执行,执行顺序就是
事件冒泡的执行顺序,先触发child 再触发parent

使用$listeners 属性可以很方便的在层级很深的组件内,立马就修改最外层的父组件内的属性值。 
注意:在vue3.0 中$listeners被移除了,将所有属性都集合到attrs里面了
// parent.vue
<m-child :data-status="dataStatus" :data-message="dataMessage"></m-child>

export default {
	data(){
		return {
			dataStatus: '123',
			dataMessage: '456'
		}
	}
}
// m-child.vue
<m-grandron v-bind="$attrs"></m-grandron>
export default {
	props:{
		dataStatus: String,
	},
	data(){
		return {}
	},
	created(){
		console.log('dataStatus',this.dataStatus)  //  123
		console.log('dataMessage',this.dataStatus)  //  456
	}
}
// m-grandron.vue
export default {
	data(){
		return {}
	},
	created(){
		console.log('dataStatus',this.$attrs)  //  {dataMessage:456} 因为child组件中props声名了dataStatus所以这里$attrs就不含有dataStatus
	}
}

//listenters*********************************************
// parent.vue
<m-child @customEvent="ev_customEvent"></m-child>

export default {
	data(){
		return {
			dataStatus: '123',
			dataMessage: '456'
		}
	},
	methods:{
		ev_customEvent(){
			console.log('my name is parent!')
		}
	}
}
// m-child.vue
<m-grandron v-on="$listeners" @customEvent="ev_customEvent"></m-grandron>
export default {
	props:{
		dataStatus: String,
	},
	data(){
		return {}
	},
	methods:{
		ev_customEvent(){
			console.log('my name is child!')
		}
	}
}
// m-grandron.vue
<button @click="$emit('customEvent')">click me!</button>
export default {
	data(){
		return {}
	},
}


// 控制台
// my name is child!
// my name is parent!

41. The data in vue is updated but the view is not updated.

**1.Vue 无法检测实例被创建时不存在于 data 中的 property**

原因:由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,
所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
解决:声明一个空值属性

**2.Vue 无法检测对象 property 的添加或移除** 

Reason: Official - Due to JavaScript (ES5) limitations, Vue.js cannot detect the addition or deletion of object properties. Because Vue.js converts properties to getters/setters when initializing an instance, the property must be on the data object for Vue.js to convert it in order for it to be responsive.
Solution: this.setthis . set this.setthis.delete


3. Vue cannot detect direct modification of an array item through array index
Reason: Official - Due to JavaScript limitations, Vue cannot detect changes in arrays and objects; You Yuxi - The performance cost is not proportional to the user experience.
Solution: Seven ways to use Vue refactoring


4. The DOM data will not change before the asynchronous update is executed.
Reason: Vue executes asynchronously when updating the DOM. As long as it listens for data changes, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed into the queue once. This deduplication during buffering is very important to avoid unnecessary calculations and DOM operations. Then, on the next event loop "tick", Vue flushes the queue and performs the actual (deduplicated) work. Vue internally tries to use native Promise.then, MutationObserver and setImmediate for asynchronous queues. If the execution environment does not support it, setTimeout(fn, 0) will be used instead.
Solution: this.$nextick


5. The loop nesting level is too deep and the view is not updated?
Solution: Use $forceUpdate() to force an update


6. When the routing parameters change, the page does not update (the data does not update).
Reason: When the routing view component references the same component, when the routing participation changes, the component cannot be updated, which is what we often say that the page cannot be updated. The problem.
Solution: Monitor $route changes through watch.
 

42. Several methods of js deep copy

For reference (object) types, this kind of copying of the object reference address is called a shallow copy. Correspondingly, if the exact same data is copied in the heap, it is called a deep copy. .
Deep copy is the result of copying data in the heap, so that operations on the copied object will not affect the original object.
Using destructuring assignment does not work at a deep level.
Using Object.create does not work at a deep level.
Using structuredClone does not work at a deep level.
Use JSON.parse and JSON.stringify
to implement it yourself
. Use third-party libraries, such as lodash.

43. vue2 data binding

var obj ={}
Object.defineProperty(obj,'txt',{
    get:function(){
       return obj
    },
    set:function(newValue){
       document.getElementById('txt').value = newValue
       document.getElementById('show').innerHTML = newValue
    }
})
document.addEventListener('keyup',function(e){
   obj.txt = e.target.value
})

44. The core of Vue’s responsive principle is Observer, Dep, and Watcher.

Responsive binding is performed in Observer. When the data is read, the get method is triggered and Dep is executed to collect dependencies, that is, to collect Watcher.
When the data is modified, the set method is triggered and updates are performed through all corresponding dependencies (Watchers). For example, watch and computed execute developer-defined callback methods.

45. Comparison of vue2 and vue3diff algorithms

Virtual dom generates a js object based on a template (using the createElement method),
and then generates a real dom based on this js object. It provides a convenient tool for
minimal DOM operations on complex document DOM structures.


When the data changes, the diff algorithm will generate a new virtual dom based on the new data. The new virtual dom will be compared with the old virtual dom. This comparison process is the diff algorithm, but because this mechanism also brings problems to the code running Some pressure inefficiencies consume memory. Some unchanging data, such as constants, will not be modified and do not need to be compared. Vue3 assigns variables to flag1 and assigns unchanged values ​​to flag. It will only compare changing values, so it has better performance than vue2. It will Find different data in the template, and re-render the template if the data is found to be different.


1. Two-way data binding between vue and vue3.
Vue2 uses the observer to hijack data and combines it with the publisher-subscriber model. All the data in the data, including the properties of the sub-property object, are added through Object.defineProperty(). Getter/setter method, use compile to parse the template and "{ {}}". When the data changes, use the update method in the watcher to notify compile to update the template. The watcher is used to monitor page data changes. Wacther combines the observer with the observer. and compile directive parser.


2. Vue3 uses Object.define.proxy to proxy objects to achieve data hijacking.
The advantage of using Proxy is that it can perfectly monitor data changes in any way. The only disadvantage is the compatibility issue,
because Proxy is ES6 syntax.
 

46. ​​Principle of has and history

hash的特性:

 1、hash只作用在浏览器,不会在请求中发送给服务器。

 2、hash 发生变化时,浏览器并不会重新给后端发送请求加载页面。

 3、修改 hash 时会在浏览器留下历史记录,可以通过浏览器返回按钮回到上一个页面。

 4、hash 发生变化时会触发 hashchange 事件,在该事件中可以通过 
window.location.hash 获取到当前 hash值。
<body>
  <ul>
    <!-- 定义路由 -->
    <li><a href="#/home">home</a></li>
    <li><a href="#/about">about</a></li>
 
    <!-- 渲染路由对应的 UI -->
    <div id="routeView"></div>
  </ul>
</body>
 
// JavaScript 部分
 
// 页面加载完不会触发 hashchange,这里主动触发一次 hashchange 事件
window.addEventListener('DOMContentLoaded', onLoad)
 
// 监听路由变化
window.addEventListener('hashchange', onHashChange)
 
// 路由视图
var routerView = null
 
function onLoad () {
  routerView = document.querySelector('#routeView')
  onHashChange()
}
 
// 路由变化时,根据路由渲染对应 UI
function onHashChange () {
  switch (location.hash) {
    case '#/home':
      routerView.innerHTML = 'Home'
      return
    case '#/about':
      routerView.innerHTML = 'About'
      return
    default:
      return
  }
}
history 路由模式的实现主要是基于下面几个特点:

1、通过 pushState 和 replaceState 两个API 来操作实现 URL 的变化

2、可以通过 popstate 事件来监听 URL 的变化,从而对页面进行跳转(渲染)

3、history.pushState() 或 history.replaceState() 
不会触发 popstate 事件,需要手动触发页面跳转

4、报404找不到页面就重定向

The difference is
that hash mode is ugly and history mode is more elegant.


The new URL set by pushState can be any URL that has the same origin as the current URL; and hash can only modify the part after #, so only the URL of the same document as the current one can be set.


The new URL set by pushState can be exactly the same as the current URL, which will also add the record to the stack; and the new value set by hash must be different from the original one to trigger the addition of the record to the stack.


pushState can add any type of data to the record through stateObject; while hash can only add short strings


pushState can additionally set the title attribute for subsequent use


hash is compatible with IE8 and above, history is compatible with IE10 and above


History mode requires the cooperation of the backend to direct all access to index.html, otherwise the user refreshes the page, which will result in a 404 error.

47. The onload event of window is different from the ready event in jquery

1. Different loading modes.
The window.onload event will wait until the DOM is created, and it will also wait until all external resources including pictures, audio, and videos are loaded before it is executed.
Disadvantages: If it takes a lot of time to load images and media content, users will feel that there is a significant delay in the execution of the code defined on the window.onload event, which affects the user experience.
The ready function in jQuery only needs to wait for the DOM to be loaded, without waiting for images or external resources to be loaded, making it faster to execute.


2. Will
the window.onload event be overwritten? If you write multiple events, the later ones will overwrite the previous ones, so you can only subscribe once.
You can write multiple $(document).ready() in jQuery in the code, and the browser will execute them in sequence according to the order in which they appear on the page.
Therefore, the ready() function in jQuery is more applicable than the window.onload event in JavaScript
 

48. Keepalive life cycle application scenarios

 keep-alive是一个抽象的组件

它自身不会渲染一个DOM元素,
也不会出现在父组件链中,使用keep-alive包裹动态组件时,
会缓存不活动的组件实例,而不是销毁它们

 作用:

在组件切换过程中将状态保留在内存中,防止重复渲染DOM,
减少加载时间及性能消耗,提高用户体验

 应用场景:  

用户在某个列表页面选择筛选条件过滤出一份数据列表,由列表页面进入数据详情页面,
再返回该列表页面,我们希望:列表页面可以保留用户的筛选(或选中)状态。

keep-alive就是用来解决这种场景。

当然keep-alive不仅仅是能够保存页面/组件的状态这么简单,
它还可以避免组件反复创建和渲染,有效提升系统性能。总的来说,
keep-alive用于保存组件的渲染状态。

 原理:

在created 函数调用时将需要缓存的VNode节点保存在this.cache中/在render(页面渲染)时,
如果VNode的name符合缓存条件(可以用include 以及 exclude控制),
则会从this.cache中取出之前缓存的VNode 实例进行渲染。
VNode:虚拟DOM,其实就是一个JS对象

 Props 的使用:

include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。

生命周期函数:
1.activated  在keep-alive 组件激活时调用 该钩子函数在服务器端渲染期间不被调用

2.deactivated 在keep-alive 组件停用时调用 该钩子在服务器端渲染期间不被调用

被包含在keep-alive 中创建的组件,会多出两个生命周期的钩子:
 activated 与deactivated

使用keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,
需要在activated阶段获取数据,承担原来created 钩子函数中获取数据的任务.

注意:只有组件被keep-alive包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,
是不会被调用的,以及在2.1.0版本之后,使用exclude排除之后,
就算被包裹在keep-alive中,这两个钩子函数依然不会被调用!
另外,在服务端渲染时,此钩子函数也不会被调用。 
<keep-alive :include="includedComponents">
  <router-view></router-view>
</keep-alive>
//或者
<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
//router.js
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello,
      meta: {
        keepAlive: false // 不需要缓存
      }
    },
    {
      path: '/page1',
      name: 'Page1',
      component: Page1,
      meta: {
        keepAlive: true // 需要被缓存
      }
    }
  ]
})

49. Usage and differences between find(), findIndex() and indexOf()

1.find()方法返回数组中第一个满足条件的元素,找不到返回undefined 该方法ES6新增。
   语法:arr.find(callback)
		callback函数有三个参数。
		item:每一次迭代查找的数组元素。
		index:每一次迭代查找的数组元素索引。
		arr:被查找的数组。 
2.findIndex()方法返回数组中第一个满足条件的索引,找不到返回-1 该方法ES6新增。
   语法:arr.findIndex(callback)
		callback函数有三个参数。
		item:每一次迭代查找的数组元素。
		index:每一次迭代查找的数组元素索引。
		arr:被查找的数组。 
3.indexOf()方法返回在数组中可以找到指定元素的第一个索引,找不到返回-1。
   语法:arr.indexOf(searchValue,[fromIndex = 0])
		searchValue:开始查找的位置数据
总结:
1.find()与findIndex()参数与用法相同,不同的是find返回元素,findIndex返回索引;找不到时find返回undefined,findIndex返回-1.
2.findIndex()与indexOf(),findIndex比indexOf更强大一些,可以通过回调函数查找对象数组,indexOf只能查找数组中指定的值,不过indexOf可以指定开始查找位置的索引 

Vite is relatively faster than webpack in vuecli, and the packaging process is omitted.

Guess you like

Origin blog.csdn.net/weixin_64948861/article/details/129178510