vue
$nextTick(function func)
- vue中用于dom的异步更新
- 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,
- 在created()钩子函数执行的时候DOM 其实并未进行任何渲染。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.$nextTick()的回调函数中。
props与$emit
- 父组件可以使用 props 把数据传给子组件。
- 子组件可以使用 $emit 触发父组件的自定义事件。
vm.$emit( event, arg ) //触发当前实例上的事件
vm.$on( event, fn );//父组件绑定事件,监听event事件后运行 fn;
v-bind,简写:
- v-bind指令用于给html标签设置属性,可以通过修饰符如:class、:style设置不同属性,
- 也能够绑定计算属性(computed),状态中data的数据是静态的,computed的属性可以计算
v-on,简写@
- v-on指令用于监听DOM事件,用法和v-bind类似,例如给button添加点击事件
v-if、v-else、v-else-if
- v-if是条件渲染指令,它根据表达式的真假来删除和插入元素
- 基本语法:
v-if=“expression”
- expression是一个返回布尔值的表达式,表达式可以是一个布尔属性,也可以是一个返回布尔的运算式。
v-show
- v-show指令与v-if类似,但是v-show不管条件是否成立,都会渲染html,通过display来控制
- 而v-if只有条件成立才会渲染
v-for
- v-for指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似
v-for=“item in list”
components属性
- 在一个组件中引用另一个属性
<template>
<!-- 3.在template中就可以直接使用了 -->
<my-component></my-component>
</template>
<script>
//1. 先使用import导入你要在该组件中使用的子组件
import MyComponent from './MyComponent.vue'
export default {
//2. 然后,在components中写入子组件
components: {
MyComponent
}
}
</script>
.native
- Vue中给自定义组件绑定原生事件需要添加.native修饰符
监听属性(watch)
// 方式一
watch: {
a(newVal, oldVal) {
//...
}
}
// 方式二
watch: {
'a.b': {
handler(newVal, oldVal) {
// ...
},
deep: true, // 深度监听
immediate: true, // 立即触发
}
}
- 一个对象,键是需要观察的表达式,值可以是对应回调函数,也可以是方法名,或者包含选项的对象。
- Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
PS: 不能使用箭头函数
计算属性
- 计算属性将会被混入到Vue实例当中,通过修改getter和setter实现数据的双向绑定
- 计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。
PS: 如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (val) {
this.a = val - 1
}
}
}
mixins
定时器
- 如果组件在创建和使用过程中添加了计时器,那么在组件切换和关闭时需要清除定时器
// 在组件销毁时(即切换组件或关闭页面),
// 调用destroyed方法清除计时器
destroyed(){
clearTimeout(this.timer)
}
Vue响应式原理
- 通俗易懂了解Vue双向绑定原理及实现
- Vue响应式基本原理:Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更新。
- 在实现过程中使用发布订阅模式,视图是订阅者,数据是发布者,添加一个依赖收集器(即订阅者管理),当数据更新时通知所有订阅者进行更新。
vuex/mutations
- 在Vuex中mutation都是同步事务,即mutations中的mutation函数必须是同步函数,异步函数无法追踪
vuex/actions
- action类似于mutation,但也有不同点:
- action提交的是mutation,而不是直接修改状态;
- action可以包含异步操作
React
React事件绑定
- 在构造函数中通过bind绑定this
- 在组件上使用箭头函数
- 实验特性: 通过匿名箭头函数的方式绑定
单向数据流(单向绑定)与双向绑定
- 与Vue的双向绑定不同,react不推荐双向绑定,这样丢失了单向数据流的特性,数据不易追踪。
- react使用props传递Function,在子组件中调用父组件传入的Function修改父组件的state,从而维持
state->props
的单向流特性
React槽与vue插槽(slot)
- 子组件通过props.children获得父组件填入槽的元素进行渲染,这种用法相当于vue中的默认插槽,children属性是自带prop
// child component
function DefaultSlot(props) {
return (
<div>
{props.children}
</div>
)
}
// parent component
function App(props) {
return (
<DefaultSlot>
<div>插槽</div>
</DefaultSlot>
)
}
- 父组件可以通过自定义的prop传入React元素供子组件渲染,因为React元素本质上就是一个对象(virtual dom)
// child component
function NamedSlot(props) {
return (
<div className="container">
<div className="left">
{props.left}
</div>
<div className="right">
{props.right}
</div>
</div>
)
}
// parent component, Left & Right is two component, it can be a React DOM, too
function App(props) {
return (
<NamedSlot
left={<Left />}
right={<Right />}
/>
)
}
React props和state的区别
把一个组件想象成一个函数,props就是函数的入参,不可编辑,state就是函数内部自定义的变量,可以修改,给定入参(props)就会返回唯一的ReactDOM
setState分场景有同步也有异步更新state
在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState是异步更新this.state(加入批处理队列中,减少更新次数),除此之外的setState调用会同步执行this.state(直接更新,不进行批处理)。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。
state哲学三问:
- 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
- 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
- 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
内嵌组件<Fragment>
- 该组件在真实节点上不会渲染,可以接受props,相当于vue中的<template>
- 可以直接使用短语法<></>
JavaScript
如何确定this的值
JavaScript深入之从ECMAScript规范解读this
Number(6)与new Number(6)
- Number全局对象由Number()构造器创建,其返回值为基本类型,通过构造器创建的是对象
6 == Number(6) == new Number(6) // true 调用valueOf()
6 === Number(6) // true
6 === new Number(6) // false
Number(6) === new Number(6) // false
箭头函数this绑定的问题
- 箭头函数没有自己的this值,箭头函数中所使用的this都是来自函数作用域链,它的取值遵循普通普通变量一样的规则,在函数作用域链中一层一层往上找
- 箭头函数的this总是指向
函数定义生效时
所在的对象。 - 当函数定义生效后(已定义),call()方法也无法更改this
var obj1 = {
name: 'obj1',
print1: function () {
return () => {
console.log(this.name)}
},
print2: function () {
return function() {
console.log(this.name)}
}
}
var obj2 = {
name: 'obj2'}
obj1.print1()() // obj1
obj1.print1().call(obj2) // obj1 obj1.print1()箭头函数已生效,call无法改变this
obj1.print1.call(obj2)() // obj2 obj1.print1获取的是代码,函数并未生效,此时call可以改变this,指向obj2,之后执行使得箭头函数定义生效
obj1.print2()() // undefined
obj1.print2().call(obj2) // obj2
obj1.print2.call(obj2)() // undefined
作用域链
继承
async/await
await 不仅仅用于等 Promise 对象,它可以等任意表达式的结果,所以,await 后面实际是可以接普通函数调用或者直接量的。
- 如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
- 如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
JS单线程的原因
- JS设计之初用于操作dom,如果多线程,某一dom节点在别的线程删除,当前线程就会出问题,此时引入锁无疑又会增加浏览器引擎的压力,本来资源就不多,所以单线程
宏任务和微任务
- 由于JS引擎线程和GUI渲染线程是互斥的关系,浏览器为了能够使宏任务和DOM任务有序的进行,会在一个宏任务执行结果后,在下一个宏任务执行前,GUI渲染线程开始工作,对页面进行渲染。而微任务可以理解成在当前宏任务执行后
立即执行
的任务
宏任务 -> 微任务 -> GUI渲染 -> 宏任务 -> …
new操作符内部原理
function myNew (func)
// 1. 生成一个对象
let obj = new Object()
// 2. 设置原型,对象原型指向构造函数的原型对象
obj.__proto__ = func.prototype
/* 上面两步可以合并 */
// Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
let obj = Object.create(func.prototype)
// 3. 绑定执行上下文对象
let result = func.call(obj)
// 4. 判断构造函数本身返回的结果是什么。基础类型直接返回,对象就返回对象
return typeof result === 'object' ? result : obj
babel编译过程
ES6+ 转成 ES5 呢,其大致分为三步:
- 将代码字符串解析成抽象语法树,即所谓的 AST
- 对 AST 进行处理,在这个阶段可以对 ES6 代码进行相应转换,即转成 ES5 代码
- 根据处理后的 AST 再生成代码字符串
目前Babel只负责parse 和 generate 流程,即专注于解析和生成阶段。transform 过程全由bable插件做
CSS
>>>
以及 /deep/
深度作用选择器
- 在Vue当中,若组件上使用scoped样式之后,只作用于当前组件,如果想要影响到子组件或者“更深”,就可以使用深度作用选择器
>>>
以及/deep/
。
HTTPS
SSL/TLS加密过程
- B端给出支持SSL协议版本号,一个客户端随机数(Client random,请注意这是第一个随机数),客户端支持的加密方法等信息;
- S端收到信息后,确认双方使用的加密方法,并返回数字证书,一个服务器生成的随机数(Server random,注意这是第二个随机数)等信息;
- B端确认数字证书的有效性,然后生成一个新的随机数(Premaster secret),然后使用数字证书中的公钥,加密这个随机数,发给S端。
- S端使用自己的私钥,获取B端发来的随机数(即Premaster secret);(第三、四步就是非对称加密的过程了)
- B端和S端通过约定的加密方法(通常是AES算法),使用前面三个随机数,生成对话密钥,用来加密接下来的通信内容;
数字证书
缓存策略
强缓存
- Expires: 在响应头中设置,是一个时间戳。如果客户端此次发送请求的时间在Expires之前,则会直接触发缓存,不再去发起请求
- Cache-Control:
- no-cache 相当于max-age=0;表示每次使用缓存时都要向服务器发送请求验证(在请求头中If-None-Match字段携带该资源上一请求返回E-tag),若返回304则使用缓存,否则使用新资源。(协商缓存确定缓存是否可用)
- no-store表示不缓存任何资源
- pulic表示客户端和代理服务器都可以缓存
- private表示只有客户端可以缓存资源
- max-age最长缓存时间(单位秒)
- Cache-Control优先级比Expires高
协商缓存(304)
校验过后返回304则直接使用本地缓存,否则使用新资源。
-
E-tag和If-No-Match(http1.1)
E-tag有服务端返回,写在响应头中。If-No-Match会携带该资源上一次请求时响应头中的E-tag值 -
Last Modified和If-Modified-Since(http1.0)
这个字段对应的时间代表服务端该资源的最后一次更改时间,当客户端再一次请求该资源时,浏览器会自动为请求添加If-Modified-Since请求头,且该请求头携带上一次Last-Modified的值。 -
1S效应
:这种方法侦测改变的时间的最小单位为1s,这意味着如果在1s的时间内,请求的资源发生了改变,也会正常触发缓存,导致客户端无法获取到最新资源。
值得一提的是,如果我们并没有配置缓存策略,浏览器会将响应头中的Date减去Last-Modified再乘以0.1,作为我们的资源缓存时间。
缓存存放位置
-
Service Worker
- 本质是作为服务器与客户端之间的代理服务器,伴随着PWA出现。Service Worker真正意义上将缓存控制权交给了前端,相比于LocalStorage、SessionStorage,后两者只是单纯的接口数据缓存,例如用户信息(一个对象)、列表信息(一个数组),而前者可以缓存静态资源,甚至拦截网络请求,根据网络状况作出不同的缓存策略。
-
memory cache
- 将资源缓存在了内存中。事实上,所有的网络请求都会被浏览器缓存到内存中,当然,内存容量有限,缓存不能无限存放在内存中,因此,注定是个短期缓存。
- 内存缓存的控制权在浏览器,前后端都不能干涉。
-
disk cache
- 将资源缓存在硬盘中,disk cache也叫http cahce,因为其严格遵守http响应头字段来判断哪些资源是否要被缓存,哪些资源是否已经过期。绝大多数缓存都是disk cache。
- 分为强制缓存与协商缓存()
-
真正的网络请求(未使用缓存,显示资源的具体大小)
Git
- 克隆仓库
git clone https://xxxx.git
- 查看分支
git branch
- 切换分支
git checkout brachName
- 切换并新建分支
git checkout -b newBranchName
- 删除分支
git branch -d brachName
- 合并分支
git merge fromBranch
- 回退远程分支
git push -f origin
- 文件大小写重命名
git mv XXXX.md YYYY.md