背景
总结前端知识点,按日为单位更新
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 中 Number 和 Date 类型的方法之一。它用于将数字或日期对象转换为特定地区的格式化字符串。
数组尾部操作的方法
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 findIndex | find返回满足条件的第一个值,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)创建的对象的原型取决于arg,arg为null,新对象是空对象,没有原型,不继承任何对象;arg为指定对象,新对象的原型指向指定对象,继承指定对象
- let,var的区别?
- 作用域方面:
let具有块级作用域,var没有块级作用域。 - 变量提升:
var存在变量提升,let的提升只声明并没有初始化。 - 重复声明:
var可以重复声明,let不可以。 - 暂时性死区:在使用
let声明变量之前,该变量都是不可用的。这在语法上成为暂时性死区。var不存在暂时性死区。
- 箭头函数和普通函数的区别
- 箭头函数的
this指向其作用域上上一级的this - 箭头函数不能作为构造函数使用,因为其没有自己的
prototype - 所以
call,bind,apply也不能改变箭头函数中this的指向
2021/12/8
- 数据类型检测的方式都有哪些?
typeofinstanceofObject.prototype.toString.callconstructor
- 判断数组检测的方式都有哪些?
-
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**。接着读取微任务队列,输出 **2,6,7** 执行完本轮的宏任务。继续执行下一轮宏任务的代码,输出 **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
数组的原生方法
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);
缺点:
- 对象中有字段值为
undefined,转换后字段会直接消失 - 对象如果有字段值为
RegExp对象,转换后则字段值会变成{} - 对象如果有字段值为
NaN,+-Infinity转换后则字段值变成null - 对象如果有
环引用,转换则直接报错 第二种:
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
缺点: 没有解决环引用的问题
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来进行逻辑处理。