组件

全局注册

  • 要注册一个全局组件,可以使用Vue.component(tagName,options)

      Vue.component('my-component', {
        // 选项
      })
    
  • 组件注册之后,便可以作为自定义元素`

html

<div id="example">
  <my-component></my-component>
</div>

js

// 注册
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

// 创建根实例
new Vue({
  el: '#example'
})

渲染为html

<div id="example">
  <div>A custom component!</div>
</div>

局部注册

  • 不必把每个组件都注册全局,可以通过某个vue实例/组件的实例选项components注册仅在其作用域中可用的组件

js

var Child = {
  template: '<div>A custom component!</div>'
}

new Vue({
  // ...
  components: {
    // <my-component> 将只在父组件模板中可用
    'my-component': Child
  }
})

组件组合

  • 在vue中,父子组件的关系可以总结为prop向下传递,事件向上传递。父组件通过prop给子组件下发数据,子组件通过事件给父组件发送消息

prop

字面量语法vs动态语法

hhtml

<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp>
  • 因为它是一个字面量 prop,它的值是字符串 "1" 而不是一个数值。如果想传递一个真正的 JavaScript 数值,则需要使用 v-bind,从而让它的值被当作 JavaScript 表达式计算:

html

<!-- 传递真正的数值 -->
<comp v-bind:some-prop="1"></comp>

prop验证

  • 要指定验证规则,需要用对象的形式来定义prop,而不能用字符串数组:

js

Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 指允许任何类型)
    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 value > 10
      }
    }
  }
})

type 可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array
  • Symbol(ES6新增了一种数据类型:Symbol,Symbol是用来定义对象的唯一属性名的不二之选;)

type也可以是一个自定义构造函数,使用instanceof检测

  • 当 prop 验证失败,Vue 会抛出警告 (如果使用的是开发版本)。注意 prop 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无法使用。

自定义事件

  • 我们知道,父组件使用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。

使用v-on绑定自定义事件

每个vue实例都实现了事件接口即:

  • 使用$on(eventName)监听事件
  • 使用$emit(eventName,optionalPayload)触发事件

给组件绑定原生事件

  • 想在某个组件的根元素上监听一个原生事件,可以使用v-on的修饰符.native。

      <my-component v-on:click.native="doTheThing"></my-component>
    

动态组件

  • 通过使用保留的 元素,并对其 is 特性进行动态绑定,你可以在同一个挂载点动态切换多个组件:
    js

      var vm = new Vue({
        el: '#example',
        data: {
          currentView: 'home'
        },
        components: {
          home: { /* ... */ },
          posts: { /* ... */ },
          archive: { /* ... */ }
        }
      })
    

html

	<component v-bind:is="currentView">
	  <!-- 组件在 vm.currentview 变化时改变! -->
	</component>
  • 也可以直接绑定到组件对象上:

      var Home = {
        template: '<p>Welcome home!</p>'
      }
      
      var vm = new Vue({
        el: '#example',
        data: {
          currentView: Home
        }
      })
    

编写可复用组件

vue组件的API来自三部分---prop,事件和插槽:

  • Prop允许外部环境传递数据给组件
  • 事件允许从组件内触发外部环境的副作用
  • 插槽允许外部环境将额外的内容组合在组件中

子组件引用

  • 尽管有 prop 和事件,但是有时仍然需要在 JavaScript 中直接访问子组件。为此可以使用 ref 为子组件指定一个引用 ID。例如:

html

	<div id="parent">
	  <user-profile ref="profile"></user-profile>
	</div>

js

	var parent = new Vue({ el: '#parent' })
	// 访问子组件实例
	var child = parent.$refs.profile
  • $refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅是一个直接操作子组件的应急方案——应当避免在模板或计算属性中使用 $refs。

高级异步组件

  • 自 2.3.0 起,异步组件的工厂函数也可以返回一个如下的对象:

      const AsyncComp = () => ({
        // 需要加载的组件。应当是一个 Promise
        component: import('./MyComp.vue'),
        // 加载中应当渲染的组件
        loading: LoadingComp,
        // 出错时渲染的组件
        error: ErrorComp,
        // 渲染加载中组件前的等待时间。默认:200ms。
        delay: 200,
        // 最长等待时间。超出此时间则渲染错误组件。默认:Infinity
        timeout: 3000
      })
    

组件命名约定

  • 当注册组件 (或者 prop) 时,可以使用 kebab-case (短横线分隔命名)、camelCase (驼峰式命名) 或 PascalCase (单词首字母大写命名)。

      // 在组件定义中
      components: {
        // 使用 kebab-case 注册
        'kebab-cased-component': { /* ... */ },
        // 使用 camelCase 注册
        'camelCasedComponent': { /* ... */ },
        // 使用 PascalCase 注册
        'PascalCasedComponent': { /* ... */ }
      }
    

内联模板

  • 如果子组件有inline-template特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板编写起来更灵活

html

<my-component inline-template>
  <div>
    <p>这些将作为组件自身的模板。</p>
    <p>而非父组件透传进来的内容。</p>
  </div>
</my-component>

X-Template

  • 另一种定义模板的方式是在JavaScript标签中使用text/x-template类型,并且指定一个id。

html

<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>

js

Vue.component('hello-world', {
  template: '#hello-world-template'
})

对滴开销的静态组件使用v-once

  • 尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来,就像这样:

      Vue.component('terms-of-service', {
        template: '\
          <div v-once>\
            <h1>Terms of Service</h1>\
            ...很多静态内容...\
          </div>\
        '
      })
    
posted @ 2018-03-14 12:16  不完美的完美  阅读(186)  评论(0编辑  收藏  举报