世界就像一个巨大的图书馆,我们读着别人,做着自己,等待被读。 :

前端框架Vue学习的心得记录(可复用性&组合)

目标:深入了解Vue框架(2.x版本)的可复用性和组合

方法:通过看Vue的官方手册(Vue官方网站

内容:本博客记录一些学习Vue中的心得,便于日后启发。(可复用性&组合)

注:遇到一些不懂的函数等,可以看官网的API参考

正文:

一、混入

1.1 基础

混入 (mixin) 提供了一种非常灵活的方式(Vue中的mixins:属性),来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

1.2 选项合并

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。注意:Vue.extend() 也使用同样的策略进行合并。

1.3 全局混入

混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。请谨慎使用全局混入,因为它会影响每个单独创建的 Vue 实例 (包括第三方组件)。大多数情况下,只应当应用于自定义选项,推荐将其作为插件发布,以避免重复应用混入。

1.4 自定义选项合并策略

自定义选项将使用默认策略,即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并,可以向 Vue.config.optionMergeStrategies 添加一个符合自己意愿的函数。对于多数值为对象的选项,可以使用与 methods 相同的合并策略。

 

二、自定义指令

1、简介

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令(Vue.directive定义,后面使用就变成了v-xx的形式)。

2、钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。

  componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  unbind:只调用一次,指令与元素解绑时调用。

3、钩子函数的参数

指令钩子函数会被传入以下参数:

el:指令所绑定的元素,可以用来直接操作 DOM 。

binding:一个对象,包含以下属性:

  name:指令名,不包括 v- 前缀。

  value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。

  oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。

   expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。

  arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。

  modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。

vnode:Vue 编译生成的虚拟节点。

oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

注意,除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

指令的参数可以是动态的。指令的参数可以是动态的。这使得自定义指令可以在应用中被灵活使用。

4、函数简写

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。就可以函数简写。

5、对象字面量

如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。

 

三、渲染函数&JSX

1、基础

Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器(使用Vue.component下的render函数)。

2、节点、树以及虚拟DOM

在深入渲染函数之前,了解一些浏览器的工作原理是很重要的。当浏览器读到一些HTML代码时,它会建立一个“DOM 节点”树来保持追踪所有内容,如同你会画一张家谱树来追踪家庭成员的发展一样。每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。

高效地更新所有这些节点会是比较困难的,不过所幸你不必手动完成这个工作。你只需要告诉 Vue 你希望页面上的 HTML 是什么,这可以是在一个模板里,或者一个渲染函数里(在这两种情况下,Vue 都会自动保持页面的更新)。

Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM。例如:

  return createElement('h1', this.blogTitle)

createElement 到底会返回什么呢?其实不是一个实际的 DOM 元素。它更准确的名字可能是 createNodeDescription,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”,也常简写它为“VNode”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。

3、createElement参数

3.1 深入数据对象

有一点要注意:正如 v-bind:class 和 v-bind:style 在模板语法中会被特别对待一样,它们在 VNode 数据对象中也有对应的顶层字段。该对象也允许你绑定普通的 HTML 特性,也允许绑定如 innerHTML 这样的 DOM 属性 (这会覆盖 v-html 指令)。

3.2 约束

VNode必须唯一,组件树中的所有 VNode 必须是唯一的。如果你真的需要重复很多次的元素/组件,你可以使用工厂函数来实现。(tips:所谓工厂函数,就是指这些内建函数都是类对象,当你调用他们时,实际上是创建了一个类实例)

4、使用JavaScript代替模板功能

4.1 v-if和v-for

只要在原生的 JavaScript 中可以轻松完成的操作,Vue 的渲染函数就不会提供专有的替代方法。比如,在模板中使用的 v-if 和 v-for,都可以在渲染函数中用 JavaScript 的 if/else 和 map 来重写。

4.2 v-model

渲染函数中没有与 v-model 的直接对应——你必须自己实现相应的逻辑。

4.3 事件&按键修饰符

对于 .passive、.capture 和 .once 这些事件修饰符, Vue 提供了相应的前缀可以用于 on。对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法。

4.4 插槽

对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法。也可以通过 this.$scopedSlots 访问作用域插槽,每个作用域插槽都是一个返回若干 VNode 的函数。如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据对象中的 scopedSlots 字段。

5、JSX

 一个 Babel 插件,用于在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上。

6、函数式组件

之前创建的锚点标题组件是比较简单,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数。 在这样的场景下,我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。

注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接收 prop,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的特性都会被自动隐式解析为 prop。 当使用函数式组件时,该引用将会是 HTMLElement,因为他们是无状态的也是无实例的。

组件需要的一切都是通过 context 参数传递,它是一个包括如下字段的对象:

  props:提供所有 prop 的对象

  children: VNode 子节点的数组

  slots: 一个函数,返回了包含所有插槽的对象

  scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。

  data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件

  parent:对父组件的引用

  listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。

  injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。

因为函数式组件只是函数,所以渲染开销也低很多。 在作为包装组件时它们也同样非常有用。比如,当你需要做这些时: 程序化地在多个组件中选择一个来代为渲染; 在将 children、props、data 传递给子组件之前操作它们。

在普通组件中,没有被定义为 prop 的特性会自动添加到组件的根元素上,将已有的同名特性进行替换或与其进行智能合并,然而函数式组件要求你显式定义该行为。如果你使用基于模板的函数式组件,那么你还需要手动添加特性和监听器。因为我们可以访问到其独立的上下文内容,所以我们可以使用 data.attrs 传递任何 HTML 特性,也可以使用 listeners (即 data.on 的别名) 传递任何事件监听器。

7、模板编译

你可能会有兴趣知道,Vue 的模板实际上被编译成了渲染函数。这是一个实现细节,通常不需要关心。但如果你想看看模板的功能具体是怎样被编译的,可能会发现会非常有意思。

 

四、插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:

  添加全局方法或者属性。如: vue-custom-element

  添加全局资源:指令/过滤器/过渡等。如 vue-touch

  通过全局混入来添加一些组件选项。如 vue-router

  添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

1、使用插件

通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成,也可以传入一个可选的选项对象。Vue.use 会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。Vue.js 官方提供的一些插件 (例如 vue-router) 在检测到 Vue 是可访问的全局变量时会自动调用 Vue.use()。然而在像 CommonJS 这样的模块环境中,你应该始终显式地调用 Vue.use()。(awesome-vue 集合了大量由社区贡献的插件和库)

2、开发插件

Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。

五、过滤器

 Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示(“|”)。你可以在一个组件的选项中定义本地的过滤器,或者在创建 Vue 实例之前全局定义过滤器,当全局过滤器和局部过滤器重名时,会采用局部过滤器。过滤器可以串联,过滤器是 JavaScript 函数,因此可以接收参数。

 

posted @ 2019-12-09 15:19  Secret_Wu  阅读(636)  评论(0编辑  收藏  举报