Vue(二 组件)

1、组件基础
1.1、复用
组件可被复用,每用一次组件,就会有一个它的新实例被创建。
组件的data必须是一个函数,每个实例可以维护一份被返回对象的独立的拷贝
1.2、注册
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。
Vue.component:全局注册
1.3、父子组件传值
父 ===》子

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

//...
<blog-post title="My journey with Vue"></blog-post>

子 ===》父
$emit

<blog-post
  ...
  v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
//...
<button v-on:click="$emit('enlarge-text')">
  Enlarge text
</button>

1.4、单个根元素
1.5、在组件上使用v-model
1.6、插槽

<alert-box>
  Something bad happened.
</alert-box>
//...
Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})

1.7、动态组件

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

已注册组件的名字,或
一个组件的选项对象
2、注册组件
2.1、命名:
例如<my-component-name>,这个组件名在注册的时候的两种写法:

Vue.component('my-component-name', { /* ... */ })
Vue.component('MyComponentName', { /* ... */ })

2.2、全局注册与局部注册
全局:Vue.component。在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。可以在各自内部互相使用
局部:全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

var ComponentA = { /* ... */ }
// ...
new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA, // 对于每个属性来说,属性名是自定义元素名字,属性值是组件的选项对象
    'component-b': ComponentB
  }
})

或者通过 Babel 和 webpack 使用 ES2015 模块

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA // ComponentA: ComponentA 的缩写
  },
  // ...
}

2.3、模块系统
单独建立一个component目录存放各种模块,在需要用到的时候可以直接import
对于一些基础组件,需要在很多地方引用,可以用到全局注册(全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生):
前提:使用了webpack (或在内部使用了 webpack 的 Vue CLI 3+);
方式:在应用入口文件 (比如 src/main.js) 中全局导入基础组件,require.context
例子参见:https://cn.vuejs.org/v2/guide/components-registration.html#%E5%9F%BA%E7%A1%80%E7%BB%84%E4%BB%B6%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8C%96%E5%85%A8%E5%B1%80%E6%B3%A8%E5%86%8C
3、prop(父向子传值)
3.1、命名

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>  // 父的驼峰式命名在子中要改成短横线分隔命名

3.2、单向数据流
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
3.3、prop验证
一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 prop 定义的
attribute。
一种写法,可以在prop中传参,value和type来检测传值的类型等
4、自定义事件
4.1、命名:全为小写(因为v-on 事件监听器在 DOM 模板中会被自动转换为全小写,HTML是大小写不敏感的)
4.2、自定义组件v-model

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

// ...
<base-checkbox v-model="lovingVue"></base-checkbox>

4.3、原生事件绑定到组件
listeners属性,v-on="listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。
4.4、.sync 修饰符
5、插槽
5.1、

<navigation-link url="/profile">
  Your Profile
</navigation-link>
// ...
<a
  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>

插槽内可以包含任何的内容
5.2、编译作用域
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
5.3、后备内容

<button type="submit">
  <slot>Submit</slot>
</button>

5.4、具名插槽

<slot name="header"></slot> //已废弃
<template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

5.5、作用域插槽
插槽内容能够访问子组件中才有的数据
绑定在 <slot> 元素上的 attribute 被称为插槽 prop

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>
// ...
<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

5.6、具名插槽的缩写
v-slot:header 可以被重写为 #header

<!-- 这样会触发一个警告 -->
<current-user #="{ user }"> //缩写只在其有参数的时候才可用,可以写成#default="{ user }"
  {{ user.firstName }}
</current-user>

6、动态组件
<keep-alive>

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

7、异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。

Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 `require` 语法将会告诉 webpack
  // 自动将你的构建代码切割成多个包,这些包
  // 会通过 Ajax 请求加载
  require(['./my-async-component'], resolve)
})
// ... 
const AsyncComponent = () => ({
  // 需要加载的组件 (应该是一个 `Promise` 对象)
  component: import('./MyComponent.vue'),
  // 异步组件加载时使用的组件
  loading: LoadingComponent,
  // 加载失败时使用的组件
  error: ErrorComponent,
  // 展示加载时组件的延时时间。默认值是 200 (毫秒)
  delay: 200,
  // 如果提供了超时时间且组件加载也超时了,
  // 则使用加载失败时使用的组件。默认值是:`Infinity`
  timeout: 3000
})

8、处理边界情况
触达另一个组件实例内部或手动操作 DOM 元素
8.1、访问父组件的根实例:root。更建议使用Vuex管理应用状态parent
ref
依赖注入
8.2、程序化事件监听器

// todo
未完成
https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E8%AE%BF%E9%97%AE%E5%AD%90%E7%BB%84%E4%BB%B6%E5%AE%9E%E4%BE%8B%E6%88%96%E5%AD%90%E5%85%83%E7%B4%A0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • 什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装...
    youins阅读 9,480评论 0 13
  • 此文基于官方文档,里面部分例子有改动,加上了一些自己的理解 什么是组件? 组件(Component)是 Vue.j...
    陆志均阅读 3,825评论 5 14
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,207评论 0 6
  • 组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应...
    前端一菜鸟阅读 860评论 0 16
  • 三、组件 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML元素,封装可重用...
    小山居阅读 611评论 0 1