前端知识总结

343 阅读23分钟
背景

总结前端知识点,按日为单位更新

React

一、生命周期

1. React的生命周期有哪些?

挂载中:

  • constructor
  • getDrivedStateFromProps
  • render
  • compontDidMount

更新中

  • getDrivedStateFromProps
    state或者props更新时调用
  • shouldCompontUpdate 用于判断是否更新渲染
  • render
  • getSnapshotBeforeUpdate 在组件更新前调用,返回值作为第三个参数传给undateDidUpdate
    这个方法通常用于获取组件更新前的一些 DOM 信息,比如滚动位置等,并在更新后恢复这些信息。
  • componentDidUpdate 该方法在组件更新完成后被调用,可以处理一些与状态或属性变化相关的操作。

卸载 componentWillUnmount

2.React 性能优化在哪个生命周期?它优化的原理是什么?

shouldCompontUpdate

3. React中发起网络请求应该在哪个生命周期中进行?为什么?

compontentDidMount

二、组件通信

React组件间常见的几种情况

  • 父组件->子组件
    ⽗组件可以向⼦组件通过传 props 的⽅式,向⼦组件进⾏通讯
  • 子组件->父组件
    props+回调
  • 兄弟组件通信
    找到这两个兄弟节点共同的⽗节点,结合上⾯两种⽅式由⽗节点转发信息进⾏通信
  • 跨级组件通信
    Context 设计⽬的是为了共享那些对于⼀个组件树⽽⾔是“全局”的数据,例如当前认证的⽤户、主题或⾸选语⾔,对于跨越多层的全局数据通过 Context 通信再适合不过
  • 发布订阅模式: 发布者发布事件,订阅者监听事件并做出反应,我们可以通过引⼊event模块进⾏通信
  • 全局状态管理⼯具: 借助Redux或者Mobx等全局状态管理⼯具进⾏通信,这种⼯具会维护⼀个全局状态中⼼Store,并根据不同的事件产⽣新的状态

二、数据管理

React中怎么校验props?验证props的目的是什么?

React为我们提供了PropTypes以供验证使用。当我们向Props传入的数据无效(向Props传入的数据类型和验证的数据类型不符)就会在控制台发出警告信息。它可以避免随着应用越来越复杂从而出现的问题。

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

当然,如果项目汇中使用了TypeScript,那么就可以不用PropTypes来校验,而使用TypeScript定义接口来校验props。

在React中组件的props改变时更新组件的有哪些方法?

React中的setState和replaceState的区别是什么?

(1)setState()  setState()用于设置状态对象。 (2)replaceState()  replaceState()方法与setState()类似,但是方法只会保留nextState中状态,原state不在nextState中的状态都会被删除。

React setState的原理

setState是同步还是异步的

1,所有setState是同步的,意味着每执行一次setState时(有可能一个同步代码中,多次setState),都重新vnode diff + dom修改,这对性能来说是极为不好的。如果是异步,则可以把一个同步代码中的多个setState合并成一次组件更新。所以默认是异步的,但是在一些情况下是同步的。
2,如果同步更新了state时,但是还没有执行render函数,那么state和props不能保持同步,state和props不能保持一致性,会在开发中产生很多的问题。

  • 异步:在React可以控制的地方,比如React生命周期事件和合成事件中,都会走合并操作,延迟更新的策略。
  • 同步:在React无法控制的地方,比如原生事件,暗送秋波就是在addEventListener、setTimeout、setInterval、等事件中,就只能同步更新。

React中有使用过getDefaultProps吗?它有什么作用?

通过实现组件的getDefaultProps,对属性设置默认值。

react中setState的第二个参数作用是什么?

是一个可选的回调函数。这个回调函数将在组件重新渲染后执行。

React基础

对React context的理解

React中,数据传递一般使用props传递数据。维持单向数据流。
Context提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树传递props。

React中refs的作用是什么?有哪些应用场景?

Refs提供了一种方式,用于访问在render方法中创建的React元素或者DOM节点。应该谨慎使用,如下场景使用Refs比较适合:

  • 处理焦点、文本选择或者媒体的控制
  • 触发必要的动画
  • 集成第三方DOM库

React组件的构造函数有什么作用?是必须的吗?

是必须的 目的:

  • 通过将对象分配給this.state来初始化本地状态
  • 将事件处理程序方法绑定到实例上 super的作用是调用父类的构造函数、属性、方法。

在React中如何避免不必要的render?

  • shouldComponentUpdate 和 PureComponent
    shouldComponentUpdate生命周期。默认情况下,每当父组件的状态或属性改变,React会重新渲染该组件及其子组件。而shouldComponentUpdate的作用就是控制组件何时重新渲染。我们可以在该方法中编写自定义的逻辑来决定是否需要更新组件。
    与普通的组件类不同,PureComponent内部已经实现了一个优化的shouldComponentUpdate方法。在这个方法中,它会对组件的属性和状态进行浅比较,只有在它们发生变化时才会触发重新渲染,否则会阻止不必要的更新。
  • 利用高阶组件
  • 使用React.memo 只能用于函数组件

对React.Fragment的理解,它的使用场景是什么?

在React中,组件返回的元素只能有一个根元素。为了不添加多余的DOM节点,我们可以使用Fragment标签来包裹所有的元素,并且Fragment标签不会渲染出任何元素。也可以写成 <></>形式

React如何获取组件对应的DOM元素?

ref,有三种方法

  • 字符串格式
class MyComponent extends React.Component {
  componentDidMount() {
    const infoElement = this.refs.info;
    console.log(infoElement); // 输出<p>元素的实例
  }

  render() {
    return <p ref="info">这是一个段落。</p>;
  }
}
  • 函数格式
class MyComponent extends React.Component {
  componentDidMount() {
    console.log(this.info); // 输出<p>元素的实例
  }

  setRef = (element) => {
    this.info = element;
  };

  render() {
    return <p ref={this.setRef}>这是一个段落。</p>;
  }
}
  • creactRef方法
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.infoRef = React.createRef(); // 创建ref对象并赋值给实例属性
  }

  componentDidMount() {
    console.log(this.infoRef.current); // 输出<p>元素的实例
  }

  render() {
    return <p ref={this.infoRef}>这是一个段落。</p>;
  }
}

React中可以在render访问refs吗?为什么?

不可以 。render阶段DOM还没有生成

对React插槽(Portals)的理解,如何使用,有哪些使用场景?

Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案

语法如下:

ReactDOM.createPortal(child, container);
  • 第一个参数clild是可渲染的React子项,比如元素,字符串或者片段等。
  • 第二个参数container是一个DOM元素。

    一般来讲,一个组件render函数返回的元素会被挂载在他的父级组件上,但是存在一些特殊情况,有些元素需要被挂载在更高级的位置。
    例如:当父组件具有overflow:hidden或者z-index的样式设置时,组件有可能被其他元素遮挡,这时就可以考虑要不要使用Portal使组件大腿挂载脱离父组件。例如:对话框,模态框。

React声明组件有哪几种方法?

  • 函数式定义的无状态组件
  • es5 原生方式的React.createClass定义的组件
  • ES6形式的 extend React.Component定义的组件

React如何判断什么时候重新渲染组件?

组件状态的改变可以因为props的改变,或者直接通过setState方法改变。
组件获得新的状态,然后React決定是否应该重新渲染。
只要组件的state发生变化,React就会对组件进行重新渲染。

哪些方法会触发React重新渲染

  • setState()方法被调用。注意当setState传入null时,不会触发渲染。
  • 父组件重新渲染 当父组件重新渲染之后,即使子组件的props未发生改变,子组件也会重新渲染,进而触发render。

React重新渲染的时候,render做了什么?

高阶函数和高阶组件HOC

高阶函数是以函数作为入参,函数作为返回值;
高阶函数得应用有:函数科里化、bind、函数防抖、函数节流。
高阶组件是一种复用组件逻辑的一种高级技巧。入参为组件,返回一个新的组件。
react-redux 中的 connect 函数、按钮权限、组件渲染性能追踪。

Render props

是指一种在React组件之间使用一个值为函数的prop共享代码的简单技术。

// DataProvider组件内部的渲染逻辑如下 
class DataProvider extends React.Components { 
    state = { name: 'Tom' } 
    render() { 
        return ( <div> <p>共享数据组件自己内部的渲染逻辑</p> 
            { this.props.render(this.state) } </div> ); 
     } 
} 
// 调用方式 
<DataProvider render={data => ( <h1>Hello {data.name}</h1> )}/>

优点:数据共享、代码复用,将组件内的state作为props传给调用者。将渲染逻辑交给调用者。
缺点:无法在return语句外访问数据,嵌套写法不够优雅。

2023/8/22

Object.is()和 === == 有什么区别?

Object.is()和===一般情况下功能相同,只是处理了一些特殊情况,比如NaN和NaN相等,-0和+0不相等。

什么是JavaScript的包装类型?

Object.keys() 、Object.values()

object.keys()用来遍历对象的键,Object.values()用来遍历对象的值

2023/8/14

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

  • 箭头函数不绑定this,只会在自己的作用域的上一层继承this。
  • 箭头函数继承来的this指向永远不变(call,bind,apply无法改变)
  • 箭头函数不能作为构造函数使用
  • 箭头函数没有prototype

对rest参数的理解

扩展运算符被用在函数形参上时,它可以把一个分离的参数序列整合成一个数组

fn(...arr){
    console.log(arr)//[1,2,3,4]
}
fn(1,2,3,4)

用于获取函数多余的参数或者参数不确定的情况

对JSON的理解

JSON是一种基于文本的轻量级的数据交换格式。它可以被任何的编程语言读取和作为数据格式来传递; 在项目开发中,使用JSON作为前后端数据交换的方式;

JavaScript脚本延迟加载的方式有哪些?

  • defer
  • async
  • 动态创建DOM方式
  • 使用setTimeout延迟方法
  • 让js最后加载

js类数组的定义

一个拥有length属性和若干索引属性的对象就可以被称为类数组对象

数组的原生方法

迭代方法
<1> some
用于检测数组中是否至少存在一项元素满足所指定的测试函数

const arr=[1,2,3,4,5]
const result = arr.some((item)=>{item>3})
console.log(result)//true

<2>every
用于检测数组中全部元素是否满足所指定的测试函数

const arr=[1,2,3,4,5]
const result = arr.every((item)=>{item>3})
console.log(result)//false

<3> map
<4> filter
<5> forEach
数组和字符串的转换方法 toString()、join ()、toLocaleString()
toLocaleString() 是 JavaScript 中 NumberDate 类型的方法之一。它用于将数字或日期对象转换为特定地区的格式化字符串。
数组尾部操作的方法 pop()、push()
数组首部操作的方法shift()、unshift()
重排序 reverse()、sort()
数组连接的方法 concat()
截取方法 slice()
数组插入方法 splice()

强类型语言和弱类型语言

  • 强类型:强制变量在使用前必须有明确的数据类型;
  • 弱类型:和强类型相反;不需要有明确的数据类型即可使用,例如js;

静态语言和动态语言

  • 静态语言在编译时进行类型检查,在变量声明时需要指定数据类型,并且类型检查错误会在编译阶段被发现。
  • 动态语言在运行时进行类型检查,在变量赋值时自动推断数据类型,并且类型检查错误可能在运行时才会被发现。

DOM和BOM

DOM:文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理网页内容得方法和接口; BOM:指的是浏览器对象模型,他指的是把浏览器当做一个对象,这个对象主要定义了与浏览器进行交互的方法和接口。

for of 与for in的区别

for of便利的是对象的键值,for in便利的是对象的键名;

数组的便利方法有哪些

方法特点
forEach没有返回值
map有返回值
filter过滤数组
for of便利的是对象的键值
every some返回布尔值 every所有条件满足返回true,some一条或者一条以上满足返回true
find findIndexfind返回满足条件的第一个值,findIndex返回满足条件的第一个值的索引

for Each和map的区别

for Each 无返回值,会改变原数组 map有返回值,不会改变原数组

2023/8/19

对原型和原型链的理解

js中除了基本类型就只有对象类型,因为js没有class类的概念,所以就有了原型和原型链的概念。 每一个实例对象都有一个私有属性__proto__指向他的构造函数的原型对象prototype,该原型对象也有一个自己的原型对象proto,层层向上直到一个对象的原型对象为null

object.prototype.__proto__ === null//true

如何获得非原型链上的属性 hasOwnProperty()

闭包

指的是有权访问另外一个函数作用域的函数 特点:
1,可以在函数外部访问到函数内部的变量
2,使已经结束的函数上下文依然保存在内存中

2021/12/7

- 字面量new出来的对象和Object.create(null)创建出来的对象有什么区别?

  • 字面量和new关键字创建的对象是Object的实例,原型指向Object.prototype,继承内置对象Object

  • Object.create(arg, pro)创建的对象的原型取决于argargnull,新对象是空对象,没有原型,不继承任何对象;arg为指定对象,新对象的原型指向指定对象,继承指定对象

- let,var的区别?

  • 作用域方面:let 具有块级作用域,var没有块级作用域。
  • 变量提升:var存在变量提升,let的提升只声明并没有初始化。
  • 重复声明: var可以重复声明,let不可以。
  • 暂时性死区:在使用let声明变量之前,该变量都是不可用的。这在语法上成为暂时性死区。var不存在暂时性死区。

- 箭头函数和普通函数的区别

  • 箭头函数的this指向其作用域上上一级的this
  • 箭头函数不能作为构造函数使用,因为其没有自己的prototype
  • 所以call,bind,apply也不能改变箭头函数中this的指向

2021/12/8

- 数据类型检测的方式都有哪些?

  • typeof
  • instanceof
  • Object.prototype.toString.call
  • constructor

- 判断数组检测的方式都有哪些?

  • Object.prototype.toString.call

  • 通过原型链判断

       obj.__proto__ === Array.prototype;
    
  • 通过ES6的Array.isArray()做判断

  • instanceof

- new的具体操作过程

  • 新建一个空对象
  • 让这个对象的__proto__指向构建他的构造函数的prototype
  • 让函数的this指向这个对象,执行构造函数。
  • 判断函数的返回值类型,如果返回值类型是值类型就返回构建的对象,如果是引用类型,就返回这个引用类型的对象
    function myNew(fn,args){
        let obj={};
        obi.__proto__=fn.prototype;
        let res=fn.apply(obj,args);
        return res instanceof Object ? res:obj; 
    }

2021/12/10

-cookie有哪些属性?

  • value
  • key
  • max_age/expire_time:设置cookie的过期时间。
  • domain:该cookie在哪个域名中有效。一般设置子域名,比如cms.example.com。
  • path:该cookie在哪个路径下有效。
  • size:大小

-js脚本延迟加载的方法有哪些?

  • defer
  • async
  • 动态创建dom,对文档的加载事件进行监听,当文档加载完成之后在动态的创建script标签
  • 使用setTimeOut 定时器延迟加载
  • 将scriipt放在文档底部,让其最后加载

-js类数组对象的定义?

  • 一个拥有 length 属性若干索引属性 的对象就可以被称为类数组对象,类数组对象和数组类似,但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果,还有一个函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数。

2021/12/13

vw,wh,vmin,vmax

  • 相对于视窗的宽度,视窗的宽度是100vw;
  • 相对于视窗的高度,视窗的高度是100vh;
  • vmin:vw,vh中的较小值
  • vmax:vw,vh中的较大值

伪元素和伪类的区别

  • 伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。他们只在外部显示可见,但不会在文档的源代码中找到他们。 ::before,::after,::first-line
  • 伪类: 将特殊的效果添加到特定的选择器上,他是已有元素上添加类别的,不会产生新的元素。 :hover,:first-child

event loop 事件循环

因为js是单线程的,所以Event loop是js处理进行异步事件的处理办法
执行栈在执行完同步任务后,检查执行栈是否为空,如果为空,检查微任务队列是否为空,如果微任务队列不为空,则一次性执行完所有的微任务。如果微任务为空。则去执行下一个宏任务。每次单个的宏任务执行完之后,都会检查微任务队列是否为空,如果不为空,则按照先进先出的方式执行完所有的微任务,然后执行下一个宏任务。

宏任务和微任务

在js中任务分为同步和异步任务,异步任务又分为宏任务和微任务。
常见宏任务
- setTimeout
- setInterval
- script标签中的代码
常见微任务
- Promise.then(非 new Promise)
- async
- await

例1:

/*** 代码一 ***/
 
console.log( "1" )
 
setTimeout(function() {
	console.log( "2" )
}, 0 )
 
setTimeout(function() {
	console.log( "3" )
}, 0 )
 
setTimeout(function() {
	console.log( "4" )
}, 0 )
 
console.log( "5" )
 
// 输出顺序 1,5, 2, 3, 4
 
 
/*** 代码二 ***/
setTimeout(function(){
    console.log('1')
});
 
new Promise(function(resolve){
    console.log('2')
    for(var i = 0; i < 10000; i++){
        i == 99 && resolve()
    }
}).then(function(){
    console.log('3')
});
 
console.log('4')
 
// 输出顺序 2,4, 3, 1


字节面试题:

console.log('1')
 
async function async1() {
    await async2() 
    console.log('2')
}
 
async function async2() {
    console.log('3')
}
async1()
 
setTimeout(function() {
    console.log('4')
}, 0)
 
new Promise(resolve => {
    console.log('5')
    resolve()
})
.then(function() {
    console.log('6')
})
.then(function() {
    console.log('7')
})
 
console.log('8')
 
// 输出顺序 1,3,5,8,2,6,7,4

//代码执行步骤分析:

①.整体 script 作为第一个宏任务进入主线程,代码自上而下执行,执行同步代码,输出 **1**

②.遇到 setTimeout,加入到宏任务队列。

③.执行 async1(),然后遇到await async2(),await 实际上是让出线程的标志,首先执行 async2(),输出 **3**;把 async2() 后面的代码console.log('2')加入微任务队列中,跳出整个 async 函数。

④.继续执行,遇到 new Promise,输出 **5**,把.then()之后的代码加入到微任务队列中。

⑤.继续往下执行,输出 **8**。接着读取微任务队列,输出 **267** 执行完本轮的宏任务。继续执行下一轮宏任务的代码,输出 **4**

  

import和require的最主要的区别,静态引用和动态引用

  • 第一次加载某个模块时,Node会缓存该模块,后续加载就从缓存中获取。require是运行时调用,所以require理论上可以运用在代码的任何地方

  • ES6模块的编译:import模块知识生成引用,等到需要时才去取值,所以不存在缓存的问题,而且模块里的变量,绑定其所在的模块,import是编译时调用

2021/12/15

如何提取高度嵌套的对象里的指定属性

当遇到一些嵌套程度非常深的对象时:

const school = {
   classes: {
      stu: {
         name: 'Bob',
         age: 24,
      }
   }
}

const { name } = school 这样解构就是错误的了,正确解法: const { classes:{ stu:{ name }} } = school

数组的原生方法

image.png

2021/12/21

深拷贝和浅拷贝

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值得一份精确拷贝。如果属性是基本类型,拷贝得就是基本类型得值,如果属性是引用类型,拷贝得就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
  • 深拷贝是将一个对象从内存中完整得拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
    var a1={b:{c:{}}}
    var a2=shallowClone(a1)//浅拷贝
    a2.b.c===a1.b.c//true
    
    var a3=deepClone(a3)//深拷贝方法
    a3.b.c===a1.b.c//false新对象和原对象不共享内存

深拷贝的实现方法
第一种

function deepClone1(obj) {
  return JSON.parse(JSON.stringify(obj));
}
const a = { name: "小庄", age: 23 };
const b = deepClone1(a);
console.log(a === b);

缺点:

  1. 对象中有字段值为undefined,转换后字段会直接消失
  2. 对象如果有字段值为RegExp对象,转换后则字段值会变成{}
  3. 对象如果有字段值为NaN,+-Infinity转换后则字段值变成null
  4. 对象如果有环引用,转换则直接报错 第二种:
function deepClone(target) {
    // 基本数据类型直接返回
    if (typeof target !== 'object') {
        return target
    }

    // 引用数据类型特殊处理
    
    // 判断数组还是对象
    const temp = Array.isArray(target) ? [] : {}
    for (const key in target) {
        // 递归
        temp[key] = deepClone(target[key])
    }
    return temp
}

const a = {
    name: 'sunshine_lin',
    age: 23,
    hobbies: { sports: '篮球', tv: '雍正王朝' },
    works: ['2020', '2021']
}
const b = deepClone(a)

console.log(b)
// {
//     name: 'sunshine_lin',
//     age: 23,
//     hobbies: { sports: '篮球', tv: '雍正王朝' },
//     works: ['2020', '2021']
// }
console.log(b === a) // false

缺点: 没有解决环引用的问题

image.png
so第三种:
目的:解决环引用问题 用map,只要便利到新的引用值,就放置到Map中,下一次如果检测到该引用值存在,那么就可以直接进行获取

function deepClone3(obj, map = new Map()) {
  let temp = Array.isArray(obj) ? [] : {};
  if (typeof obj !== "object") {
    return obj;
  }
  if (map.get(obj)) {
    return map.get(obj);
  }
  map.set(obj, temp);
  for (let num in obj) {
    temp[num] = deepClone3(obj[num], map);
  }
  return temp;
}
const a3 = { name: "小庄", age: 23 };
const b3 = deepClone3(a3);
console.log(a3 === b3);

vue的基本原理

当一个Vue实例创建时,Vue会遍历data中的属性,用Object.defineProperty(Vue3.0使用proxy)将它们转为getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
每个组件实例都有下供应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

2021/12/25

双向数据绑定的原理

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

computed和watch的区别

对于Computed:

  • 支持缓存,只有依赖的数据发生了变化,才会重新计算

  • 不支持异步,当Computed中有异步操作时,无法监听数据的变化

  • computed的值会默认走缓存,计算属性时基于他们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的

  • 如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed

  • 如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值,在computer中,属性有get和set方法,当数据发生变化时,会调用set方法 Watch:

  • 不支持缓存,数据变化时,他就会触发相应的操作

  • 支持异步监听

  • 监听的函数接受两个参数,第一个参数是最新的值,第二个参数是变化之前的值、

  • 当一个属性发生变化时,就需要执行相应的操作 可以说,想要执行异步或者昂贵的操作以响应不断的变化时,就需要使用watch

运用场景: 当需要进行数值计算,并且依赖其他数据时,应该使用computed,因为可以利用computed的缓存特性,避免每次获取值都要重新获取计算 当需要在数据变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许执行异步操作(一个api)限制执行该操作的频率,并在得到最终结果前,设置中间状态,这些都是计算属性无法做到的。

2021/12/25

过滤器的作用

过滤数据,Vue中使用filters来过滤数据,filters不会修改数据,只是过滤,改变用户看到的输出 使用场景:

  • 需要格式化数据的情况,比如需要处理时间,价格等数据格式的输出/显示
  • 比如后端返回一个年月日的日期字符串,前端需要展示为多少天前的数据格式,此时就可以用filters过滤器来处理 用法:
<li>商品价格:{{item.price | filterPrice}}</li>

 filters: {
    filterPrice (price) {
      return price ? ('¥' + price) : '--'
    }
  }

v-if和v-show的区别

  • v-if是动态的向DOM树内添加或者删除DOM元素
  • v-show是通过设置DOM元素的display样式属性控制显隐(实际存在于文档流中,只是控制它显示不显示)

data为什么是一个函数而不是对象

对象是引用类型,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化。 所以组件的数据写成函数的形式,数据以函数返回值的形式定义,这样每次复用组件时,就会返回一个新的data

Vue中给data中的对象属性添加一个新的属性时会发生什么?如何解决

<script>
    export default { 
       data () { 
          return { 
              obj: { 
                  a: 'obj.a' 
              } 
          } 
       },
       methods: { 
          addObjB () { 
              this.obj.b = 'obj.b' 
              console.log(this.obj) 
          } 
      }
   }
</script>

数据添加之后,视图未刷新,因为在Vue实例创建时,obj.b并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api $set():

addObjB () (
   this.$set(this.obj, 'b', 'obj.b')
   console.log(this.obj)
}

$set()方法相当于手动的去把obj.b处理成一个响应式的属性,此时视图也会跟着改变了。

2020/5/11

keep-alive中的生命周期有哪些

保存组件状态,进行缓存,防止多次渲染。 把组件包裹之后会多出来两个生命周期 deactivated,activated。 同时beforeDestroy和destroyed就不会再被触发了。

当组件被换掉时,会被缓存到内存中、触发 deactivated 生命周期;当组件被切回来时,再去缓存里找这个组件、触发 activated钩子函数。

hash和history的区别

hash:改变hash的值,不会重新加载页面。因为hash的值只会出现在url中,不会出现在http请求中,所以对后端完全没有影响。

history:没有#,后端根据用户输入的url来进行逻辑处理。