vue2笔记+源码分析(仅仅是个笔记)

第一章 对vue的大概认识

1.vue的特点

  1. 采用组件化模式—————提高代码的复用率、让代码更好的维护
  2. 声明式编码————————编码人员无需直接操作DOM,提高开发效率。
  3. 使用虚拟DOM+优秀的Diff算法————尽量复用DOM节点。

2.MVVM

  1. view视图层:负责展示model中的数据;
  2. model模型层:负责数据的存储和业务逻辑;
  3. viewmodel视图模型层:负责连接model和view,具有双向绑定能够自动更新视图。

优点:

  • 分离view和model,降低代码耦合,提高视图或逻辑的重用性;
  • 自动更新视图。

缺点:

  • Bug很难被调试

MVVM的原理:

  1. Vue基类

3.SPA(single-page application)单页面应用

仅在页面初始化时加载相应的HTML、JavaScript和CSS,一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转,而是利用路由机制实现HTML内容的变换,避免页面的重新加载。
1.优点

  • 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;服务器压力小;
  • 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。
    2.缺点
  • 初次加载耗时长;
  • SEO(搜索引擎优化)难度高;
  • 页面复杂都提高,复杂逻辑程度成倍。

4.MPA(MultiPage Application)多页面应用

每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。

5.Vue的生命周期

所谓的vue生命周期指的是vue实例从创建到销毁的过程。

在vue的生命周期过程中,某些函数在特定的时候会自动被调用,即生命周期函数。

  • 前四个函数在整个生命周期中只执行一次,为创建阶段的生命周期函数
  • 一共三个阶段:创建(4)————运行(2)————销毁(2)
  • 如果要处理与数据相关的逻辑,最早在created函数中进行处理。
  • 在实例创建完成后created被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

1.beforeCreate(创建前)
数据代理,$data存在
2.created(创建后) :①(可)数据初始化,ajax请求数据可以放在这里
配置了el选项或者手动调用vm.$mount(el)进入mount流程————都没有,不会进入mount流程
模板的编译,ast=>优化=>生成render函数字符串,render函数执行,渲染为内存中的DOM,Vnode
3.beforeMount(挂载前)
挂载到页面,el 被新创建的 vm.$el 替换(create vm.$el and replace "el" with it)
4.mounted(挂载后)
一旦数据发生改变:
5.beforeUpdate(更新前)
6.updated(更新后)

关闭网站、网页
7.beforeDestroy(销毁前)
8.destroyed(销毁后)

vue/src/core/instance/index.js

——————vue的构造函数,new Vue(options)调用的就是该函数。
function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
——————initMixin(Vue)在Vue的原型上挂载了init方法
 Vue.prototype._init = function (options?: Object) {
 ....
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)//...包括initData() data = vm._data = typeof data === 'function'? getData(data, vm): data || {}
    //proxy(vm, `_data`, key)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
 }
 
——————lifecycleMixin(Vue)

6.Vue的模板编译

  • parse 函数解析 template,把字符串类型的 template 转化成了树状结构的 AST(Abstract Syntax Tree)。
  • optimize 函数会对 parse 生成的 AST优化静态内容,静态内容指的是和数据没有关系,不需要每次都刷新的内容。, 之后diff 算法会直接跳过静态节点。
  • generate 函数生成 render function code

接下来 Vue 做的事情就是 new watcher,这个时候会对绑定的数据执行监听,render 函数就是数据监听的回调所调用的,其结果便是重新生成 vnode。

当这个 render 函数字符串在第一次 mount、或者绑定的数据更新的时候,都会被调用,生成 Vnode。

如果是数据的更新,那么 Vnode 会与数据改变之前的 Vnode 做 diff,对内容做改动之后,就会更新到真正的 DOM 上。

以上是在<tempalte>模板标签中的内容,当不是用的.vue文件,而是采用script标签引入的vue.js,同时也没有用template模板属性时: vue会把由el指定的dom中的内容作为模板,编译模板再挂载回dom元素上。

vue/src/compiler/index.js

export const createCompiler = createCompilerCreator(function baseCompile (
  template: string,
  options: CompilerOptions
): CompiledResult {
  const ast = parse(template.trim(), options)
  if (options.optimize !== false) {
    optimize(ast, options)
  }
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})

第二章 API(难点)

1.Vue.extend

Vue.extend(options)返回的是一个新的VueComponent构造函数。(在模板中遇到该组件名称作为标签的自定义元素时,Vue解析时就会创建组件的实例对象,即Vue自己执行:new VueComponent(options))

组件实例均是VueComponent的实例对象,组件和Vue实例不能划等号。 区别:

  • 组件实例不能用el
  • 组件实例data必须写成函数
内置关系

VueComponent.prototype.__proto__===Vue.prototype
目的:让组件实例对象可以访问到Vue原型上的方法。

2.Vue.use

Vue.use(插件)用来加载插件。
插件上的原理: 对象中的特殊的install方法,会接受vm参数(Vue的构造函数),向Vue构造函数中添加Vm.prototype.$loading=loading

  1. 传入插件,检查插件是否被注册,若注册过则直接跳出。
  2. 在处理入参时,将第一个参数之后的参数归集,并在首部塞入this上下文。
  3. 执行注册,如果插件没有install方法并且插件为函数则直接执行插件本身,否则调用插件上定义好的install方法传入处理的参数

第三章 插件

1.Vuex

组件调用store提供的api:Dispatch(动作类型,数据)————操作行为触发方法。这里可直接commit.

Vuex中有三个对象:(store来管理三个对象,store.dispatch(),store.commit())

  • actions操作行为处理模块。api:commit(动作类型,数据)————状态改变提交操作方法。 const actions = { jia(context,value){ context.commit('JIA',value); } }
  • mutations状态改变操作方法。 const mutations = { JIA(state,value){ state.sum += value; } }
  • state页面状态管理容器对象。 const state = { sum:0, }

其他:

  • getters const getters = { bigSum(state){return state.sum*10} }

2.VueRouter

Vue.use(VueRouter)后,组件上多了$router,路由实例

第四章 配置项

1.render

render:h=>h(app)

data(){
    return{
        people:['小孩','大人']
    }
 },
render(createElement){
 return createElement(this.tag,{},this.people.map(name=>createElement('li',{//第一个参数可以是组件
 attrs:{class:'test'},
 on:{click:()=>{console.log('li')}}
 },name)))
}

第五章 属性

1.ref

是document.getElementById()等原生获取dom的替代者,ref标识。

this.$refs.值

值得注意的是:

对于组件标签,id拿到的是dom结构,而ref却能拿到组件实例对象。

2.v-on

绑定自定义事件:v-on:demo="getStudentName"

this.$refs.student.$on('demo',this.getStudentName) 触发自定义事件:this.$emit("demo",this.name)