组件注册

  • 组件名
     Vue.component('my-component-name', { /* ... */ })

    这里的my-component-name就是组件名,组件名的取法可以参考指南

    • kebab-case写法(-连接单词) 推荐的写法

      定义:

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

      用法:

        <my-component-name></my-component-name>
    • PascalCase写法(单词首字母大写)

        Vue.component('MyComponentName', { /* ... */ })
  • 全局注册
      Vue.component('my-component-name', { /* ... */ })
  • 局部注册

    先用一个普通的 JavaScript 对象来定义组件:
      var ComponentA = { /* ... */ }
    var ComponentB = { /* ... */ }

    然后在 components 选项中定义你想要使用的组件:

      new Vue({
    el: '#app',
    components: {
    'component-a': ComponentA,
    'component-b': ComponentB
    }
    })

    对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。

    注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:

      var ComponentA = { /* ... */ }
    
      var ComponentB = {
    components: {
    'component-a': ComponentA
    },
    // ...
    }

    或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:

      import ComponentA from './ComponentA.vue'
    
      export default {
    components: {
    ComponentA
    },
    // ...
    }
  • 模块系统

    通过 import/require 使用一个模块系统

    • 模块系统中局部注册
      import ComponentA from './ComponentA'
    import ComponentC from './ComponentC' export default {
    components: {
    ComponentA,
    ComponentC
    },
    // ...
    }

prop

  • prop大小写(camelCase vs kebab-case)

    HTML 中的特性(属性)名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:

      Vue.component('blog-post', {
    // 在 JavaScript 中是 camelCase 的
    props: ['postTitle'],
    template: '<h3>{{ postTitle }}</h3>'
    })
      <!-- 在 HTML 中是 kebab-case 的 -->
    <blog-post post-title="hello!"></blog-post>

    因此,强烈建议kebab-case写法。

  • prop 类型

    通常,以字符串数组形式列出 prop:

      props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

    但是,通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:

      props: {
    title: String,
    likes: Number,
    isPublished: Boolean,
    commentIds: Array,
    author: Object,
    callback: Function,
    contactsPromise: Promise // or any other constructor
    }
  • 传递静态或动态prop

    传递静态值:

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

    传递动态值

      <!-- 动态赋予一个变量的值 -->
    <blog-post v-bind:title="post.title"></blog-post> <!-- 动态赋予一个复杂表达式的值 -->
    <blog-post
    v-bind:title="post.title + ' by ' + post.author.name"
    ></blog-post>

    实际上,能传递的值包括:字符串、数字、布尔值、数组、对象、对象所有属性。

  • 单向数据流

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。

  • prop验证

      Vue.component('my-component', {
    props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
    type: String,
    required: true
    },
    // 带有默认值的数字
    propD: {
    type: Number,
    default: 100
    },
    // 带有默认值的对象
    propE: {
    type: Object,
    // 对象或数组默认值必须从一个工厂函数获取
    default: function () {
    return { message: 'hello' }
    }
    },
    // 自定义验证函数
    propF: {
    validator: function (value) {
    // 这个值必须匹配下列字符串中的一个
    return ['success', 'warning', 'danger'].indexOf(value) !== -1
    }
    }
    }
    })

    上面的type可以是原生构造函数的一个:StringNumberBooleanArrayObjectDateFunctionSymbol

  • 非 Prop 的特性

    一个非 prop 特性是指传向一个组件,但是该组件并没有相应 prop 定义的特性。

    • 替换/合并已有的特性

      对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值,classstyle 特性会稍微智能一些,即两边的值会被合并起来。
    • 禁用特性继承

      组件的选项中设置 inheritAttrs: false ,适合配合实例的 $attrs 属性使用:
        Vue.component('base-input', {
      inheritAttrs: false,
      props: ['label', 'value'],
      template: `
      <label>
      {{ label }}
      <input
      v-bind="$attrs"
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
      >
      </label>
      `
      })

自定义事件

  • 事件名

    不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称:

      this.$emit('myEvent')

    则监听这个名字的 kebab-case 版本是不会有任何效果的:

      <!-- 没有效果 -->
    <my-component v-on:my-event="doSomething"></my-component>

    推荐始终使用 kebab-case 的事件名

  • 自定义组件的 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>
  • 将原生事件绑定到组件

    使用 v-on 的 .native 修饰符:

      <base-input v-on:focus.native="onFocus"></base-input>

    Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了作用在这个组件上的所有监听器。可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。

      Vue.component('base-input', {
    inheritAttrs: false,
    props: ['label', 'value'],
    computed: {
    inputListeners: function () {
    var vm = this
    // `Object.assign` 将所有的对象合并为一个新对象
    return Object.assign({},
    // 我们从父级添加所有的监听器
    this.$listeners,
    // 然后我们添加自定义监听器,
    // 或覆写一些监听器的行为
    {
    // 这里确保组件配合 `v-model` 的工作
    input: function (event) {
    vm.$emit('input', event.target.value)
    }
    }
    )
    }
    },
    template: `
    <label>
    {{ label }}
    <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on="inputListeners"
    >
    </label>
    `
    })
  • .sync 修饰符

    update:myPropName 的模式触发事件

      this.$emit('update:title', newTitle)
      <text-document
    v-bind:title="doc.title"
    v-on:update:title="doc.title = $event"
    ></text-document>

    缩写:

      <text-document v-bind:title.sync="doc.title"></text-document>

    同时设置多个 prop :

      <text-document v-bind.sync="doc"></text-document>

插槽

  • 插槽内容

     <navigation-link url="/profile">
    Your Profile
    </navigation-link>

    <navigation-link> 的模板中:

      <a v-bind:href="url" class="nav-link">
    <slot></slot>
    </a>

    Your Profile会替换<slot></slot>部分。Your Profile可以是HTML代码或者其他插件。

  • 编译作用域

    父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

      <navigation-link url="/profile">
    Clicking here will send you to: {{ url }}
    <!--
    这里的 `url` 会是 undefined,因为 "/profile" 是
    _传递给_ <navigation-link> 的而不是
    在 <navigation-link> 组件内部定义的。
    -->
    </navigation-link>
  • 后备内容(默认值)

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

    这里的Submit就是默认值。

  • 具名插槽

    <slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

      <div class="container">
    <header>
    <slot name="header"></slot>
    </header>
    <main>
    <slot></slot>
    </main>
    <footer>
    <slot name="footer"></slot>
    </footer>
    </div>

    一个不带 name<slot> 出口会带有隐含的名字“default”。

    在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

      <base-layout>
    <template v-slot:header>
    <h1>Here might be a page title</h1>
    </template> <p>A paragraph for the main content.</p>
    <p>And another one.</p> <template v-slot:footer>
    <p>Here's some contact info</p>
    </template>
    </base-layout>
  • 作用域插槽

    绑定在 <slot> 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:

      <current-user>
    <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
    </template>
    </current-user>
    • 独占默认插槽的缩写语法

        <current-user v-slot:default="slotProps">
      {{ slotProps.user.firstName }}
      </current-user>
    • 解构插槽 Prop

        <current-user v-slot="{ user }">
      {{ user.firstName }}
      </current-user>
  • 动态插槽名

      <base-layout>
    <template v-slot:[dynamicSlotName]>
    ...
    </template>
    </base-layout>
  • 具名插槽的缩写

    (v-slot:) 替换为字符 #

  • 其它示例(略)

动态组件&&异步组件

  • 在动态组件上使用 keep-alive

    曾经在一个多标签的界面中使用 is 特性来切换不同的组件:

      <component v-bind:is="currentTabComponent"></component>

    可以用一个 <keep-alive> 元素将其动态组件包裹起来,避免切换的时候重新渲染:

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

处理边界情况

这些特殊场景和危险情况需要留心~

  • 访问元素 & 组件

    • 访问根实例

      $root属性
    • 访问父级组件实例

      $parent属性
    • 访问子组件实例或子元素

      ref特性
    • 依赖注入

      新的实例选项:provideinject
  • 程序化的事件侦听器

    • 通过 $on(eventName, eventHandler) 侦听一个事件
    • 通过 $once(eventName, eventHandler) 一次性侦听一个事件
    • 通过 $off(eventName, eventHandler) 停止侦听一个事件
  • 循环引用

    • 递归组件
    • 组件之间的循环引用
  • 模板定义的替代品

    • 内联模板
    • X-Template
  • 控制更新

    • 强制更新

      $forceUpdate
    • 通过 v-once 创建低开销的静态组件

从零开始的vue学习笔记(四)的更多相关文章

  1. vue学习笔记(四)事件处理器

    前言 在上一章vue学习笔记(三)class和style绑定的内容中,我们学习了如何在vue中绑定class和style,介绍了常用的绑定方法,class的数组绑定和对象绑定以及style的数组绑定和 ...

  2. 从零开始的vue学习笔记(一)

    前言 项目要用vue.js,今天开始自学vue.js官方教程,记录下自己的学习摘要,方便后面查阅(此笔记按照学习天数,每天一篇) Vue.js是什么 Vue是一套用于构建用户界面的渐进式框架,Vue ...

  3. 从零开始的vue学习笔记(八)

    前言 今天花一天时间阅读完Vue Router的官方文档的基础部分,简单的做一下总结和记录 Vue Router是什么 Vue Router 是 Vue.js 官方的路由管理器,用于构建单页应用(SP ...

  4. 从零开始的vue学习笔记(五)

    单文件组件 Vue.component 来定义全局组件的缺点: 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复 字符串模板 (String te ...

  5. Vue学习笔记四:跑马灯效果

    目录 跑马灯原理 HTML 箭头函数 计时器 跑马灯效果 跑马灯原理 先讲讲跑马灯的原理,就是一行字,会滚动,思路是这样的,使用substring方法,一个获取字符串的第一个字,一个获取1后面所有的字 ...

  6. VUE 学习笔记 四 计算属性和监听器

    1.计算属性 对于任何复杂逻辑,你都应当使用计算属性 <div id="example"> <p>Original message: "{{ me ...

  7. 从零开始的vue学习笔记(二)

    数据与方法 当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中.data的数据和视图同步更新. 实例创建后添加一个新的属性,对这个属性的的改动将不会触发任何 ...

  8. 从零开始的vue学习笔记(七)

    前言 今天花一天时间阅读完vuex的官方文档,简单的做一下总结和记录 Vuex是什么 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,以前的符合"单向数据流"理念的 ...

  9. 从零开始的vue学习笔记(六)

    混入 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能.简单解释就是把一个Vue组件中的内容提供给别的组件来用.例子: // 定义一个混入对象 var myMixin ...

随机推荐

  1. Python爬虫之小试牛刀——使用Python抓取百度街景图像

    之前用.Net做过一些自动化爬虫程序,听大牛们说使用python来写爬虫更便捷,按捺不住抽空试了一把,使用Python抓取百度街景影像. 这两天,武汉迎来了一个德国总理默克尔这位大人物,又刷了一把武汉 ...

  2. 2018 Multi-University Training Contest 3(部分题解)

    Problem F. Grab The Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Ja ...

  3. 05 python内置函数大全

    一.数学运算 abs:返回数字的绝对值 abs(-1) round:保留浮点数的小数位数,默认保留整数.四舍五入. round(1.553,1) #1.6 divmod:计算除数和被除数的结果,并返回 ...

  4. 数据库常用SQL语句(二):多表连接查询

    前面主要介绍了单表操作时的相关查询语句,接下来介绍一下多表之间的关系,这里主要是多表数据记录的查询,也就是如何在一个查询语句中显示多张表的数据,这也叫多表数据记录的连接查询. 在实现连接查询时,首先是 ...

  5. elementUI树状图竖向滚动条和横向滚动条问题

    添加样式: <div class="device-tree"> <el-scrollbar style="height:100%"> & ...

  6. IDEA新建一个最简单的Maven的JavaWeb项目

    1.项目环境 IDEA:2016.2 JDK:1.8.0_76 Maven:3.2.5 2.File-->New-->Project-->Maven 3.选择Project SDK: ...

  7. 第一次作业:学习C++指针

    1 内存空间的访问方式 计算机的内存存储器被划分为一个个存储单元.储存单元按一定的规则编号,这个编号就是存储单元的地址.地址编码的基本单位是字节,每个字节由8个二进制位组成,也就是说每个字节是一个基本 ...

  8. .NET Core 3.0 Preview 9 发布

    翻译自官方博客 今天,我们宣布推出.NET Core 3.0 Preview 9.就像预览版8一样,我们专注打磨最终版本的.NET Core 3.0,而不是添加新功能.如果这些最终版本看起来不像早期预 ...

  9. AirFlow简介

    1, 简介 ​ Airflow是一个可编程,调度和监控的工作流平台,基于有向无环图(DAG),airflow可以定义一组有依赖的任务,按照依赖依次执行.airflow提供了丰富的命令行工具用于系统管控 ...

  10. Hessian 接口使用示例总结(转载)

    一.使用hessian接口准备 首先,hessian接口的使用,必须要准备hessian接口的jar包,本文使用的jar包如下:hessian-4.0.7.jar; Hessian接口的使用一般是在两 ...