官方文档
https://v2.cn.vuejs.org/v2/guide/
组件传值
对象
1 | export default { |
传值的时候
1 | <SubjectNum :ele-props="subjectList" /> |
列表
1 | export default { |
传值的时候
1 | <SubjectNum :subject-list="subjectList" /> |
组件名大小写
定义组件名的方式有两种:
使用 kebab-case
1 | Vue.component('my-component-name', { /* ... */ }) |
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。
使用 PascalCase
1 | Vue.component('MyComponentName', { /* ... */ }) |
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。
也就是说<my-component-name>
和<MyComponentName>
都是可接受的。
注意:
尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
<template>
标签内的就是字符串模版,直接操作DOM的就不是字符串模版。
组件通讯
父传子
子组件中定义
1 | props: ["showpage", "currpage", "pages"] |
父组件中传递
1 | v-bind:showpage="showpage" |
子传父
子组件中调用
1 | this.$emit('gotopage', newValue, oldValue); |
父组件中传递
1 | v-on:gotopage="gotopage" |
非父子组件的通信
事件定义
1 | window.zevent = new Vue() |
发送事件
1 | window.zevent.$emit('formNodeCLick',data); |
接收事件
1 | window.zevent.$on("formNodeCLick", (data) => { |
双向绑定
双向绑定是通过发送input来实现的。
1 | this.$emit("input", this.selectArr); |
插槽
单个插槽
组件模板中可能会写为:
1 | <template> |
调用组件时这样写:
1 | <z-card style="margin-top: 10px"> |
当组件渲染的时候,<slot></slot>
将会被替换为<div>Hello</div>
。插槽内可以包含任何模板代码,包括 HTML。
注意:
组件标签内部用来替换<slot></slot>
中的取值标签不能取到组件内的变量。
如果navigation-link
没有包含一个<slot></slot>
元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
多个插槽
<slot>
元素有一个特殊的 attribute
:name
。
这个 attribute 可以用来定义额外的插槽:
1 | <div class="container"> |
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以 v-slot
的参数的形式提供其名称:
1 | <base-layout> |
现在 <template>
元素中的所有内容都将会被传入相应的插槽。
任何没有被包裹在带有 v-slot
的 <template>
中的内容都会被视为默认插槽的内容。
一个不带 name
的 <slot>
出口会带有隐含的名字default
。
然而,如果你希望更明确一些,仍然可以在一个 <template>
中包裹默认插槽的内容:
1 | <base-layout> |
应用范围
全局组件
方式1
1 | import LoadingComponents from './components/loading/loading.vue'; |
方式2
如何通过Vue.use()
来使用呢?
在组件的同级目录下,再创建一个index.js文件(名字可以随便起)
1 | import LoadingComponents from './loading.vue'; |
引入自定义组件,并使用
1 | import Vue from 'vue' |
局部组件
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
引用文件
如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
1 | import ComponentA from './ComponentA.vue' |
注意在 ES2015+ 中,在对象中放一个类似
ComponentA
的变量名其实是ComponentA: ComponentA
的缩写
使用JS
可以通过一个普通的 JavaScript 对象来定义组件:
1 | var ComponentA = { /* ... */ } |
然后在 components
选项中定义你想要使用的组件:
1 | new Vue({ |
对于 components
对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
注意:局部注册的组件在其子组件中不可用。
分页组件示例
1 | Vue.component('zj-page', { |
使用方法
1 | <zj-page v-bind:showpage="showpage" v-bind:currpage="currpage" v-bind:pages="pages" v-on:gotopage="gotopage"></zj-page> |
JS代码
1 | new Vue({ |
注意:在分页组件内部,点击页数后 并没有直接在自定义组件内修改当前页数,而是发送了一个事件,让父组件来更新页数,
是因为Vue的属性传递是
单向
的