知识整理和分享(框架篇)

vue

生命周期,父子组件执行的顺序

话不多说,直接上图:

new Vue() => beforeCreat
beforeCreate
new Vue(),在实例初始化之后,数据观测和暴露了一些有用的实例属性和方法
数据观测,在vue的响应式系统中加入data对象中所有的数据,也就是通过双向绑定去实现。
暴露属性和方法,就是vue实例自带的一些属性和方法。

created
在处理完 inject 后,紧接着就做了 props 、methods 、data 、computed 和 watch 的初始化处理;

beforeMount 和 mounted
首先会去判断是否有 el 属性,有的话就继续往下执行生命周期,要是没有的话再去判断是否有vm.$mount(手动挂载),如果这个也没有的话就只会执行到created生命周期就结束了。
当有 el 属性或者 vm.$mount 的时候,还会继续往下执行到 template 属性的判断。
1.首先内部实例有 template 属性的时候直接用内部的,然后调用render函数去渲染;
2.如果内部实例没有 template 属性,就调用外部的 html,实例内部的template比外部的优先级高;
3.要是两者都不满足,那么就抛出错误。
关于created生命周期的几个问题:
1.为什么 el 属性的判断要在template 之前? 答:因为 el 是一个选择器,vue实例需要用这个 el 去 template 中寻找对应的
2.实际上vue实例还有一种render选项,优先级是 render函数 > template属性 > 外部html
3.vue的编译过程就是把template编译成render函数的过程

创建vue实例的$el,然后用它替代el属性

beforeUpdate 和 updated
数据发生变化时,视图也会随之发生变化;数据改变导致虚拟dom的改变,然后再调用这两个生命周期去改变视图
注:这个数据只有和模版中的数据绑定了才会发生更新

beforeDestroy 和 destroyed
在beferoDestory生命钩子调用之前,所有实例都可以用,但是当调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁

几个不常用的生命钩子
activated: 当组件激活时触发
deactivated: 当组件停用的时候触发
errorCaptured:2.5.0之后的版本才有的,当捕获一个来自子孙组件的错误时被调用

beforeCreate :初始化了部分参数,如果有相同的参数,做了参数合并,执行 beforeCreate ;
created :初始化了 Inject 、Provide 、 props 、methods 、data 、computed 和 watch,执行 created ;
beforeMount :检查是否存在 el 属性,存在的话进行渲染 dom 操作,执行 beforeMount ;
mounted :实例化 Watcher ,渲染 dom,执行 mounted ;
beforeUpdate :在渲染 dom 后,执行了 mounted 钩子后,在数据更新的时候,执行 beforeUpdate ;
updated :检查当前的 watcher 列表中,是否存在当前要更新数据的 watcher ,如果存在就执行 updated ;
beforeDestroy :检查是否已经被卸载,如果已经被卸载,就直接 return 出去,否则执行 beforeDestroy ;
destroyed :把所有有关自己痕迹的地方,都给删除掉;

父子组件之间的传值,组件之间的通讯

  1. props / $emit
  2. $children / $parent
  3. provide / reject
  4. ref
  5. eventBus
  6. vuex
  7. localStorage / sessionStorage
  8. $attrs / $listeners
    对于隔代组件而言,可以使用的通信方式有:
    1.prop一代一代下传然后再一代一代往上传;
    2.使用eventBus,但是这种方式多人开发时不方便维护;
    3.使用vuex来做数据管理,但是如果只是传值,而没有数据的处理改变的话使用vuex是有点大材小用了。
    因此,在vue的2.4版本中,引入了$attrs 和 $listeners 新增了inheritAttrs 选项可以用来实现此功能。例子如下:
// app.vue
// index.vue
<template>
  <div>
    <child-com1
      :name="name"
      :age="age"
      :gender="gender"
      :height="height"
      title="程序员成长指北"
    ></child-com1>
  </div>
</template>
<script>
const childCom1 = () => import("./childCom1.vue");
export default {
  components: { childCom1 },
  data() {
    return {
      name: "zhang",
      age: "18",
      gender: "女",
      height: "158"
    };
  }
};
</script>

// childCom1.vue
<template class="border">
  <div>
    <p>name: {{ name}}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = () => import("./childCom2.vue");
export default {
  components: {
    childCom2
  },
  inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    name: String // name作为props属性绑定
  },
  created() {
    console.log(this.$attrs);
     // { "age": "18", "gender": "女", "height": "158", "title": "程序员成长指北" }
  }
};
</script>

// childCom2.vue

<template>
  <div class="border">
    <p>age: {{ age}}</p>
    <p>childCom2: {{ $attrs }}</p>
  </div>
</template>
<script>

export default {
  inheritAttrs: false,
  props: {
    age: String
  },
  created() {
    console.log(this.$attrs); 
    // { "gender": "女", "height": "158", "title": "程序员成长指北" }
  }
};
</script>

在vue2.4中新增选项inheritAttrs,inheritAttrs的默认值为true,这时父组件中的不被认作props的属性将会作为普通的html特性应用在子组件的根元素上;如果将inheritAttrs改为false,这些默认的行为将会去掉,同时可以通过设置实例属性 a t t r s , 可 以 将 这 些 特 性 生 效 , 并 且 同 时 可 以 通 过 v − b i n d 绑 定 到 子 组 件 的 非 根 元 素 上 面 。 同 理 attrs,可以将这些特性生效,并且同时可以通过v-bind绑定到子组件的非根元素上面。同理 attrs,vbindlisteners是使用在子组件传值给父组件的时候用到的。

常见使用场景可以分为三类:
父子组件通信: props; $parent / $children; provide / inject ; ref ; $attrs / l i s t e n e r s 兄 弟 组 件 通 信 : e v e n t B u s ; v u e x 跨 级 通 信 : e v e n t B u s ; V u e x ; p r o v i d e / i n j e c t 、 listeners 兄弟组件通信: eventBus ; vuex 跨级通信: eventBus;Vuex;provide / inject 、 listeners:eventBus;vuex:eventBusVuexprovide/injectattrs / $listeners

computed wacth 区别

computed 是计算属性,类似于过滤器,对绑定到视图的数据进行处理并监听变化进而执行相应的方法;计算属性是基于它们的依赖进行缓存的,只有相关的依赖发生改变的时候才会触发方法重新计算。
watch 是一个监听的动作,用来观察和响应Vue实例上的数据变动
相同点:两者都是起到一个监听/依赖一个数据,并进行处理
不同点:computed主要用于对同步数据的处理,watch则主要用于观测某个值的变化去完成一段开销比较大的复杂业务逻辑,能用computed的情况下优先使用computed

wacth 的高级用法:
1.handler方法和immediate属性
在初始化的时候watch是不会执行的,但是我们可以通过这种方式让他初始化的时候执行:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: {
      handler(val) {
        console.log('第一次执行了~')
        this.fullName = val + ' ' + this.lastName
      },
      // 代表在watch里声明了firstName这个方法之后立即先去执行handler方法
      immediate: true
    }
  }
})

我们在这里给firstName绑定了一个handler方法,这个其实就是watch的默认方法,但是真正起作用的是后面的immediate:true,这个属性就表示如果watch里面声明了初始化的对象的话就会立即去执行里面的handler方法
2.deep属性
在watch中还有一个deep属性,代表是否开启深度监听,默认是false。
我们知道Vue不能检测到对象属性的添加或删除,由于Vue会在初始化实例的时候对属性执行 getter/setter转化过程,所以属性必须在data里面存在才可以转化它,才可以是响应式的。但是如果我们在watch中加上了这个deep:true属性的话就可以深度的监听对象属性里面的值。

如何实现一个指令

  1. 先实现一个自定义指令的处理逻辑
  2. 使用Vue.directive(key, directives[key]) 来注册组件
  3. 最后在mian.js引入进来使用Vue.use()初始化就好了

vue-router实现原理

在vue这样的spa(单页应用)页面中,不仅页面交互是无刷新的,连页面的跳转也是不刷新页面的,但是为了实现正常的页面跳转就有了前端路由。原理也是一就是匹配不同的url路径然后动态渲染出不同的html页面,但是如果每次url都变化的话页面是会重新刷新的,那么解决问题的思路就是在保证url变化的情况下页面不刷新,在html5之前是使用的hash来实现的,url hash 就类似于 www.baidu.com/#/home
hash
hash 的每次变化会触发hashchange这个事件,通过这个事件我们就可以监听到hash值的改变,并且知道具体改变的值,然后我们再通过监听不同的值来实现页面渲染不同的html
history
在html5的标准里,有了pushState 和 replaceState 2个api,pushState可以往页面的history中添加了一个状态;replaceState是将当前的url替换成目标url地址并且不会改变history的长度。同时还有一个popstate事件,当活动历史记录条目更改时,将触发popstate事件。不过这种模式需要在后台去配置好所有情况的候选资源,在特定的情况下就直接指向到根页面。

vue.nextTick实现原理

vue中的nextTick可以在DOM更新完毕之后执行一个回调。
1.实现原理是用异步队列的方式来控制dom更新和nextTick回调先后顺序;
2.microtack因为优先级高,能确保队列中的为任务在下一次宏任务之前执行;
3.由于兼容的问题,vue做了向下降级方案,使用的是macrotack来实现

vue mixin 实现原理

vue类上面的data函数会与子类的data函数合并,得到一个新的函数,这个函数会在子类实例化时执行,同时执行父类和子类的data函数,然后返回合并后的data对象,这样mixin的对象就可以在子类中获取到了。

双向绑定的实现(伪代码实现)

vue实现双向绑定的原理,首先是通过Object.defineProperty()方法重写this.$data里面属性的get和set方法,实现了监听数据的改变,同时又通过发布订阅者的模式实现了数据更改的同时更新视图,同时在视图更新的时候也会更改数据的值。

双向绑定是指数据模型(Module)和视图(View)之间的双向绑定。
其原理是采用数据劫持结合发布者-订阅者模式的方式来实现。
Vue中先遍历data选项中所有的属性(发布者)用Object.defineProperty劫持这些属性将其转为getter/setter。读取数据时候会触发getter。修改数据时会触发setter。
然后给每个属性对应new Dep(),Dep是专门收集依赖、删除依赖、向依赖发送消息的。先让每个依赖设置在Dep.target上,在Dep中创建一个依赖数组,先判断Dep.target是否已经在依赖中存在,不存在的话添加到依赖数组中完成依赖收集,随后将Dep.target置为上一个依赖。
组件在挂载过程中都会new一个Watcher实例。这个实例就是依赖(订阅者)。Watcher第二参数式一个函数,此函数作用是更新且渲染节点。在首次渲染过程,会自动调用Dep方法来收集依赖,收集完成后组件中每个数据都绑定上该依赖。当数据变化时就会在seeter中通知对应的依赖进行更新。在更新过程中要先读取数据,就会触发Wacther的第二个函数参数。一触发就再次再次自动调用Dep方法收集依赖,同时在此函数中运行patch(diff运算)来更新对应的DOM节点,完成了双向绑定

Object.defineProperty 与 Proxy 的区别

Object.defineProperty是使用在vue3.0之前的数据劫持中的,proxy是es6中新增加的一个对象,用于修改某些操作的默认行为,等同于在语言层面做一些修改;
proxy可以理解为,在目标对象之前架设一个“拦截”,外界对对象的访问都必须要通过这个拦截。
在vue3.0中的双向绑定就是通过proxy来实现的,他可以支持get set apply construct 等这些拦截操作。
对比:
Object.defineProperty
1.在vue中,Object.defineProperty无法监控到数组的下标变化,导致直接通过数组下标给数组设值,不能实时的响应,所以vue给出了特定的一些数组方法来监听数组的变化。
2.Object.defineProperty只能劫持对象的属性,因此我们需要对对象进行遍历,直到把对象里面所有的子属性都遍历完,这个就对性能有一定的损耗
proxy
1.可以劫持整个对象,返回一个新的对象
2.有13种劫持操作,方便使用

另外一个版本:
Object.defineProperty

不能监听到数组length属性的变化;
不能监听对象的添加;
只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。

Proxy

可以监听数组length属性的变化;
可以监听对象的添加;
可代理整个对象,不需要对对象进行遍历,极大提高性能;
多达13种的拦截远超Object.defineProperty只有get和set两种拦截

vuex

vuex是什么?有什么作用?
vuex是一个使用在vue.js中的状态管理工具,它采用集中式存储管理应用的所有组件的状态,唯一的改变状态的方法是提交mutation。
vuex解决了:
1.在vue中多个组件同时依赖同一状态时,在多层的组件之间的传值非常的繁琐,并且对于兄弟组件之间的传值无能为力;
2.来自不同组件的行为需要变更同一状态,在没有vuex之前是需要父子组件直接引用或者通过传递事件来实现,这会造成项目变的难以维护。
Vuex中action和mutation有什么区别?
action 提交的是一个mutation,而不是直接变更状态
action 中可以包含异步操作
mutation是vuex中唯一改变store状态的唯一方法。
vuex数据的流向
单向数据流
在这里插入图片描述
vuex实现的原理?
vuex的双向绑定实现,其实是通过调用 new Vue 来实现的,然后再通过Vue mixin 注入到Vue的生命周期中去的,然后再通过劫持state.get方法,将数据放入组件中

react

生命周期

https://www.jianshu.com/p/514fe21b9914
组件的初始化阶段 initialization
这个阶段主要是处理react class 的constructor构造方法
组件的挂载阶段 mounting
componentWillMount
在组件挂载到dom之前调用,只会调用一次。
render
根据组件的props和state,return一个React元素,不负责实际的渲染工作,之后就由react自身根据元素去渲染出页面dom,是一个纯函数,不可在里面执行this.setState
componentDidMount
组件挂载到dom后调用一次,只会调用一次
组件的更新阶段
componentWillReceiveProps(nextProps)
此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新的props,但是这个值不一定保证是更改过的,所以一般是需要我们在这个生命周期中去根据nextProps和this.props判断的。
shouldComponentUpdate(nextProps, nextState)
此生命周期通过对比nextProps,nextState 和 this.props,this.state,决定是否需要更新组件。
componentWillUpdate
此生命周期在调用render方法之前执行,在这里可以执行一些更新前的操作
render
再次调用render方法,返回一个react元素
componentDidUpdate(prevProps, prevState)
此生命周期在更新完成之后调用,可以操作组件更新的dom,prevProps,prevState指的是组件更新之前的props和state
卸载阶段
componentWillUnmount
此生命周期在组件卸载之前调用,这里可以执行一些清理工作,以免引起内存泄露

新版生命周期 react16.4之后
getDerivedStateFromProps
其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代
在这里插入图片描述
static getDerivedStateFromProps(props, state) 在组件创建时和更新时的render方法之前调用,它应该返回一个对象来更新状态,或者返回null来不更新任何内容。

getSnapshotBeforeUpdate
getSnapshotBeforeUpdate() 被调用于render之后,可以读取但无法使用DOM的时候。它使您的组件可以在可能更改之前从DOM捕获一些信息(例如滚动位置)。此生命周期返回的任何值都将作为参数传递给componentDidUpdate()

数据流 - redux redux-thunk redux-saga dva

在这里插入图片描述
react 的数据流是单向数据流,只能从父组件传到子组件,因此在一些大一点的项目中我们都会引入redux来统一管理数据和状态
在这里插入图片描述
saga
在这里插入图片描述
dva
在这里插入图片描述

react 父子组件之间的传值方式

父组件向子组件传值主要是使用props的方式传值,子组件向父组件传值的话可以使用绑定事件的方法传递

虚拟dom - diff算法

Virtual dom是页面dom的抽象,实质上是一个js对象,是更加轻量级的对页面dom的描述
使用Virtual dom可以提升页面内容改变时的渲染效率,在js对象层面去对比页面dom的变动,然后将差异的部分一次性的在页面上渲染;同时正是由于Virtual Dom的存在,使得前端可以更好的实现跨平台
diff算法
就是在每次Virtual Dom变更的时候,通过比较2个虚拟树的差异,得到差异的对象,然后再把差异的对象应用到真正的dom树上

hook

Hook是react 16.8的新增特性,Hook是一些可以让你在函数组件里面去 钩入 React state 及生命周期等特性的函数。
useState 主要的作用是可以在组件中通过调用useState来给组件添加一些内部的state.
useEffect 比如我们在传统的class中需要去监听组件更新,可能是需要在componentDidMount 和 componentDidUpdate中同时去处理,但是使用hook的话就只需要在useEffect中监听就可以了,他是在dom更新之后就会去执行

高阶组件 hoc

高阶组件就是一个没有副作用的纯函数,各个高阶组件不会互相依赖耦合,接受一个组件作为参数,然后返回一个新的组件出来。
在redux中的content的就是一个高阶函数,把mapStateToProps和mapDispatchToProps解构之后传递给了原组件,这样我们就可以在原组件中去获取到这些属性了。

三、2者的对比

vue:vue的整体思想还是体现经典的 html + css + js 的形式,比如vue中的template 和 模板中的指令等。同时vue对组件的数据进行了监听,实现了数据的双向绑定

react:整体上是函数式的思想,组件使用jsx语法,all in js,将html与css全都融入javaScript,jsx语法相对来说更加灵活,当组件调用setState或props变化的时候,组件内部render会重新渲染,子组件也会随之重新渲染,可以通过shouldComponentUpdate或者PureComponent可以避免不必要的重新渲染。

在团队技术选型上,首先需要考虑的是项目的类型适合哪种技术,然后是在发展的角度考虑技术选型,同时还需要了解团队中技术人员的技术储备来综合考虑。

四、对于docker的了解

docker是一种性能非常好的虚拟机
docker相比于传统的虚拟机的技术来说先进了不少,具体表现在dokcer不是在宿主机器上重新分配一块空间来跑虚拟机,而是直接运行在宿主机上(会做文件和网络的隔离),这样docker的体积会更小,更轻便,同时也更快,宿主机下创建的个数也可以更多

五、flutter的使用和特点

优点:不需要桥接层,直接原生实现,用户体验和流畅度会更好,有谷歌这个亲爸爸推广。之后的发展不可小觑。
缺点:编程语言是Dart,对于前端来说上手难有是会有一些的,代码会比较长,嵌套逻辑会比较深。
使用flutter还是有一些差异的,首先语法的不同,然后是万物皆组件,样式的书写让人很蛋疼,特别是刚开始接触的时候,书写的贼不爽。

对MVVM的理解

在这里插入图片描述
在Model和View之间多了叫做View-Model的一层,将模型与视图做了一层绑定关系,在理想情况下,数据模型返回什么试图就应该展示什么

https://segmentfault.com/a/1190000015783546

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值