从零开始的vue学习笔记(四)

组件注册

  • 组件名

     Vue.component('my-component-name', { /* ... */ })
    这里的my-component-name就是组件名,组件名的取法可以参考指南
    • kebab-case写法(-连接单词) 推荐的写法
      定义:

        Vue.component('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: '

    {{ postTitle }}

    ' })
      
      
    因此,强烈建议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
    传递静态值:

      

    传递动态值

      
      
    
      
      

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

  • 单向数据流

    所有的 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: `
              
          `
          })

自定义事件

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

      this.$emit('myEvent')

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

      
      
    推荐始终使用 kebab-case 的事件名
  • 自定义组件的 v-model

      Vue.component('base-checkbox', {
      model: {
          prop: 'checked',
          event: 'change'
      },
      props: {
          checked: Boolean
      },
      template: `
          
      `
      })
      
  • 将原生事件绑定到组件
    使用 v-on 的 .native 修饰符:

      

    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: `
          
      `
      })
  • .sync 修饰符
    update:myPropName 的模式触发事件

      this.$emit('update:title', newTitle)
      

    缩写:

      

    同时设置多个 prop :

      

    插槽

  • 插槽内容

     
      Your Profile
      

    的模板中:

      
      
      

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

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

      
      Clicking here will send you to: {{ url }}
      
      
  • 后备内容(默认值)

      

    这里的Submit就是默认值。

  • 具名插槽
    元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

      

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