[关闭]
@jsongao98 2021-04-24T12:17:00.000000Z 字数 13204 阅读 51

Vue重点

JavaScript


响应式(双向数据绑定), 数据驱动(单向数据流),MVVM与MVC

此处输入图片的描述

此处输入图片的描述
此处输入图片的描述

vue实例在初始化时候会使用Object.defineProperty()遍历data中的所有property,设置getter/setter(访问器属性)
初始化完之后才是生命周期钩子函数beforeCreated()

对于对象,数组,因为存的是引用,所以无法检测变化。对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

已存在的对象动态添加响应式属性:

  • 单个值的属性 : vm.$set(this.someObject,key,value)
  • 想添加的属性是对象? : this.someObject = Object.assign( {},this.someObject,{......} )


    数组

  • 想通过数组索引添加响应值:还是用vm.$set(this.someArray,index,value)
  • 改变了数组长度?:通过splice方法


  • 作用域/实例/组件:

    通过new Vue创建的根实例,是Vue类,组件是通过Vue.extends继承自Vue类:在渲染组件的时候三步走,初始化子类(组件)构造函数,安装组件钩子函数和实例化 vnode。


    组件通信:


    双向数据绑定(v-model):

    1.在表单控件中使用:

    v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
    text 和 textarea 元素使用 value property 和 input 事件;
    checkbox 和 radio 使用 checked property 和 change 事件;
    select 字段将 value 作为 prop 并将 change 作为事件。
    value + input 以及 checked || selected + change的语法糖
    语法糖: v-model="x" 相当于 :value = "x" @input = (value) => "x"= value
    将model层的变量与表单控件的value||checked||selected绑定
    并监听控件上的input||change事件,事件接受一个参数(value),赋值给model层变量

    2.在组件中使用:
    组件内this.$emit('input',this.value),组件上v-model 监听我们自定义的input事件
    自定义组件model选项:

    1. Vue.component('base-checkbox', {
    2. model: {
    3. prop: '2checked',//组件上默认使用value的prop名和input事件,自定义我们要绑定的prop名
    4. event: 'change'//自定义要emit的事件
    5. },
    6. props: {
    7. 1checked: Boolean//从组件上传入的值
    8. },
    9. template: `
    10. <input
    11. type="checkbox"
    12. v-bind:2checked="1checked"
    13. v-on:change="$emit('change', $event.target.2checked)"
    14. >
    15. `
    16. })
    17. <base-checkbox v-model="lovingVue"></base-checkbox>//
    18. 这里的 lovingVue 的值将会传入这个名为 checked prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue property 将会被更新。
    19. 注意你仍然需要在组件的 props 选项里声明 checked 这个 prop

    新增.sync修饰符:(提供一种双向绑定)

    1. <text-document
    2. v-bind:title="doc.title"
    3. v-on:update:title="doc.title = $event"
    4. ></text-document>
    1. <text-document v-bind:title.sync="doc.title"></text-document> //上边例子的语法糖
    1. <text-document v-bind.sync="doc"></text-document>
    2. 这样会把 doc 对象中的每一个 property (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。注意不能使用对象字面量语法。

    双向数据绑定原理

    Vue采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter(或通过遍历对象和数组),在数据变动时发布消息给订阅者,触发相应的监听回调。
    参考:https://ustbhuangyi.github.io/vue-analysis/v2/reactive/

    此处输入图片的描述


    computed与watch

    computed

    watch


    diff

    https://github.com/aooy/blog/issues/2


    生命周期:

    此处输入图片的描述


    此处输入图片的描述


    生命周期钩子 组件状态 最佳实践
    beforeCreated 实例初始化之后,this指向创建的实例,不能访问到data、computed、watch、methods上的方法和数据 常用于初始化非响应式变量
    created 实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到$el属性,$ref属性内容为空数组 常用于简单的ajax请求,页面的初始化
    beforeMount 在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数 --
    mounted 实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问 常用于获取VNode信息和操作,ajax请求
    beforeUpdate 响应式数据更新时调用,发生在虚拟DOM打补丁之前 适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
    updated 虚拟 DOM 重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作 避免在这个钩子函数中操作数据,可能陷入死循环
    beforedDestory 实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例 常用于销毁定时器、解绑全局事件、销毁插件对象等操作
    destoryed 实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁 --
    vm.$nextTick 将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。 --

    注意:

       1. created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态
    
       2.mounted 不会承诺所有的子组件也都一起被挂载(如果子组件包含异步组件)。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick,但异步组件(通过() => import(...))也是和nextTick中的callback函数一样存在于微任务队列中,执行分先后顺序,有时会导致nextTick被执行时候,异步组件的加载任务还停留在微任务队列中,导致callback无法获取异步组件中的内容。
    
       3.vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,如果实在需要这样用可以在这个生命周期钩子中手动移除dom节点
    



      单个组件的生命周期
    1. 初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted四个钩子函数
    2. 当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
    3. 当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
    4. 初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行



      父子组件的生命周期
    1. 仅当子组件完成挂载后,父组件才会挂载
    2. 当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
    3. 父子组件在data变化中是分别监控的(更新子组件的data不会调用到父组件钩子),但是在更新props中的数据是关联的
    4. 销毁父组件时,先将子组件销毁后才会销毁父组件



    有关组件生命周期参考:https://juejin.cn/post/6844903602356502542#heading-3


    为什么是虚拟dom(vnode)

    一方面是出于性能方面的考量:

    • 创建真实DOM的代价高:真实的 DOM 节点 node 实现的属性很多,而 vnode 仅仅实现一些必要的属性,相比起来,创建一个 vnode 的成本比较低。
    • 触发多次浏览器重绘及回流:使用 vnode ,相当于加了一个缓冲,让一次数据变动所带来的所有 node 变化,先在 vnode 中进行修改,然后 diff 之后对所有产生差异的节点集中一次对 DOM tree 进行修改,以减少浏览器的重绘及回流

    但是性能受场景的影响是非常大的,不同的场景可能造成不同实现方案之间成倍的性能差距,所以依赖细粒度绑定及 Virtual DOM哪个的性能更好不是一个容易下定论的问题。

    更重要的原因是为了解耦HTML依赖,这带来两个非常重要的好处是:

    • 不再依赖 HTML 解析器进行模版解析,可以进行更多的 AOT 工作提高运行时效率:通过模版 AOT 编译,Vue 的运行时体积可以进一步压缩,运行时效率可以进一步提升;
    • 可以渲染到 DOM 以外的平台,实现 SSR、同构渲染这些高级特性,Weex 等框架应用的就是这一特性。

    综上,Virtual DOM 在性能上的收益并不是最主要的,更重要的是它使得 Vue 具备了现代框架应有的高级特性。

    • Virtual DOM 除了它的数据结构的定义,映射到真实的 DOM 实际上要经历 VNode 的 create、diff、patch 等过程。那么在 Vue.js 中,VNode 的 create 是通过之前提到的 createElement 方法创建的,

    Vue Router


    Vuex


    Vue-loader是什么?

    vue-loader 是一个 webpack 的 loader,可以将单文件组件SFC转换为 JavaScript 模块

    • 默认支持 ES2015;

    • 允许对 Vue 组件的组成部分使用其它 webpack loader,比如对 <style> 使用 Sass 和对 <template> 使用 Jade;
      .vue 文件中允许自定义节点,然后使用自定义的 loader 进行处理;

    • <style><template> 中的静态资源当作模块来对待,并使用 webpack loader 进行处理;

    • 对每个组件模拟出 CSS 作用域;

    • 支持开发期组件的热重载。

    Vue知识点

    class,style绑定


    条件渲染,列表渲染


    事件处理:

    v-on 缩写@

    在内联语句处理器中访问原始DOM事件,可以用特殊变量
    $event传入方法内

  • 事件修饰符:
    .stop(相当于原生DOM的event.stopPropagation)
    .prevent(preventDefault)
    .capture(addEventListener(..,capture = true))
    .once(只监听一次后取消该监听器)
    .self(只当在 event.target是当前元素自身时触发处理函数
    即事件不是从内部元素触发的 )
    .passive
    使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

  • 按键修饰符:
    跟在keyup/keydown等事件后面

    1. <input v-on:keyup.page-down="onPageDown">//
    2. 在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。

    .enter
    .tab
    .delete (捕获“删除”和“退格”键)
    .esc
    .space
    .up
    .down
    .left
    .right

  • 系统修饰键:
    可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

    .ctrl
    .alt
    .shift

  • .exact 修饰符

    1. <!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
    2. <button v-on:click.ctrl="onClick">A</button>
    3. <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    4. <button v-on:click.ctrl.exact="onCtrlClick">A</button>
    5. <!-- 没有任何系统修饰符被按下的时候才触发 -->
    6. <button v-on:click.exact="onClick">A</button>

  • 鼠标按钮修饰符:
    .left
    .right
    .middle
    这些修饰符会限制处理函数仅响应特定的鼠标按钮。

    新增$listener对象:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners"传入内部组件——在创建更高层次的组件时非常有用

    1. Vue.component('base-input', {
    2. inheritAttrs: false,
    3. props: ['label', 'value'],
    4. computed: {
    5. inputListeners: function () {
    6. var vm = this
    7. // `Object.assign` 将所有的对象合并为一个新对象
    8. return Object.assign({},
    9. // 我们从父级添加所有的监听器
    10. this.$listeners,
    11. // 然后我们添加自定义监听器,
    12. // 或覆写一些监听器的行为
    13. {
    14. // 这里确保组件配合 `v-model` 的工作
    15. input: function (event) {
    16. vm.$emit('input', event.target.value)
    17. }
    18. }
    19. )
    20. }
    21. },
    22. template: `
    23. <label>
    24. {{ label }}
    25. <input
    26. v-bind="$attrs"
    27. v-bind:value="value"
    28. v-on="inputListeners"
    29. >
    30. </label>
    31. `
    32. })

    插槽:

    具名插槽:template里的内容代替带有该name属性的slot
    作用域插槽:
    在子组件模板中,<slot>绑定attribute,在父组件模板中,插槽template中通过插槽slotProps.attribute来访问子组件作用域的变量。

    1. 父组件模板中
    2. <子组件>
    3. <template v-slot:header = "slotProps">
    4. slotProps.attribute1/2/...//来访问子组件作用域的变量的内容
    5. </template>
    6. <子组件>
    1. 子组件模板中
    2. <slot name="header" :attribute1="变量1" :attribute2="变量2" ....>默认内容</slot>
    1. 作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里:
    2. function (slotProps) {
    3. // 插槽内容
    4. }
    5. 这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop

    slotProps:{
        attr1:{},
        attr2:{},
        ...
    }


    SPA与MPA:

    此处输入图片的描述

  • 添加新批注
    在作者公开此批注前,只有你和作者可见。
    回复批注