组件

组件是可复用的 Vue 实例,且带有一个名字。

<div id="components-demo">
<button-counter></button-counter>
</div>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {count: 0}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
});
new Vue({ el: '#components-demo' })
</script>

注意:

  • 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
  • 每个组件必须只有一个根元素
  • 有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。
  • 全局注册的组件可以在任何父组件或者子组件使用,局部注册的组件在其子组件中不可用。
  • 全局注册的行为必须在根 Vue 实例 (通过 `new Vue`) 创建之前发生。
  • 当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
  • 对于绝大多数 attribute 来说,从外部提供给组件的值会替换掉组件内部设置好的值。class 和 style attribute 会稍微智能一些,即两边的值会被合并起来
  • inheritAttrs: false 选项不会影响 style 和 class 的绑定。

注册组件

  • 全局注册:Vue.component('comp-name',{})
  • 局部注册:new Vue(components:{ 'comp-name':{},comp-obj })
  • 组件命名:
    • my-component
    • MyComponent
  • 使用模块系统注册
    <script>
    import ComponentA from './ComponentA';
    export default {components: {ComponentA}}
    </script>
  • require.context: 只全局注册这些非常通用的基础组件。

    link:https://cn.vuejs.org/v2/guide/components-registration.html

自定义组件的v-model

<div id-"comp">
<base-checkbox v-model="lovingVue" ></base-checkbox>
</div>
<script>
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
//注意你仍然需要在组件的 props 选项里声明 checked 这个 prop。
props: {checked: Boolean},
template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)">`
})
new Vue({
el: '#comp',
data:{return { lovingVue: true}},
methods:{}
})
</script>

传参

  • props

    用一个 props 选项将其包含该组件可接受的 prop 列表

    • 可以为其指定类型props:{title: String}或者props:{title: {type: String}}
    • 为其指定类型域props:
    • type: [ String | Number | Boolean | Array | Object | Date | Function | Symbol | 自定义的构造函数]
    • 指定默认值props:{title: {default: "post-title"}}
    • 指定是否必须props:{title: {required: true}}
    • 指定验证函数 props:{title: {validator: function(v){return ['A','B'].indexOf(v) !== -1}}}
  • <div id="comp">
    <blog-post title="My journey with Vue"></blog-post>
    </div>
    <script>
    Vue.component('blog-post', {
    props: {'title'},
    template: '<h3>{{ title }}</h3>'
    })
    new Vue(el:'#comp')
    </script>
  • $emit

    通过调用内建的 $emit 方法并传入事件名称来触发一个事件,操作父组件的data

    <div id="comp">
    <blog-post v-on:click-count="click += 1" title="My journey with Vue"></blog-post>
    </div>
    <script>
    Vue.component('blog-post', {
    props: {'title'},
    template: `<div><button @click="$emit('click-count')">Enlarge text</button><h3>{{ title }}</h3></div>`
    })
    new Vue(el:'#comp',data:{return {click:1}})
    </script>
  • v-slot

    绑定在 <slot> 元素上的 attribute 被称为插槽 prop。

    <div id="comp">
    <current-user :user='user'>
    <!-- 提取默认命名插槽的props -->
    <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
    </template>
    </current-user>
    <!-- 解构赋值提取默认命名插槽的user -->
    <current-user v-slot="{ user }">{{ user.firstName }}</current-user>
    <!-- 解构赋值提取默认命名插槽的user并自定义命名person -->
    <current-user v-slot="{ user: person }">{{ person.firstName }}</current-user>
    <!-- 解构赋值提取默认命名插槽的user并自定义属性默认值,用于插槽 firstName 是 undefined -->
    <current-user v-slot="{ user = { firstName: 'Guest' } }">{{ user.firstName }}</current-user>
    <!-- 动态指令参数也可以用在 v-slot 上,来定义动态的插槽名 -->
    <current-user v-slot:[dynamicSlotName]="{ user }">{{ user.firstName }}</current-user>
    <!-- v-slot:slotName="props"可以缩写成#slotName="props" -->
    <current-user #default="{ user }">{{ user.firstName }}</current-user>
    </div>
    <script>
    Vue.component('current-user',{
    props:{user:Object},
    template:`<span><slot v-bind:user="user">{{ user.lastName }}</slot></span>`
    })
    new Vue({
    el: '#comp',
    data:{
    return {
    user{
    firstName:'misuha',
    lastName:'White'
    },
    dynamicSlotName:'default'
    }
    }
    })
    </script>
  • slot & slot-scope ( 已废弃 )

    <div id="comp">
    <current-user :user='user'>
    <template slot="default" slot-scope="{user}">{{ user.firstName }}</template>
    </current-user>
    </div>
    <script>
    Vue.component('current-user',{
    props:{user:Object},
    template:`<span><slot v-bind:user="user">{{ user.lastName }}</slot></span>`
    })
    new Vue({
    el: '#comp',
    data:{
    return {
    user:{
    firstName:'sa',
    lastName:'wh'
    },
    dynamicSlotName:'default'
    }
    }
    })
    </script>

<slot>

和 HTML 元素一样,我们经常需要向一个组件传递内容

当组件渲染的时候,<slot></slot> 将会被替换为“Something bad happened.”。插槽内可以包含任何模板代码,包括 HTML

<div id="alarm-comp">
<alert-box>Something bad happened.</alert-box>
</div>
<script>
Vue.component('alert-box', {
template: `<div class="demo-alert-box"><strong>Error!</strong><slot></slot</div>`
})
new Vue(el:'#alarm-comp')
</script> <!--默认值,它只会在插槽没有提供内容的时候被渲染。-->
<button type="submit"><slot>Submit</slot></button>
<!--具名插槽(组件名:‘base-layout’),默认值name='default'-->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
<!--为具名插槽赋值-->
<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>
<!--为具名插槽赋值的缩写-->
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
<current-user #default="{ user }">{{ user.firstName }}</current-user>

is

在不同组件之间进行动态切换

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
<!-- 这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。 -->
<table>
<blog-post-row></blog-post-row>
</table>
<!-- 这个特殊的 is attribute 给了我们一个变通的办法 -->
<table>
<tr is="blog-post-row"></tr>
</table>

禁用 Attribute 继承

如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。

<script>
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
</script>

$listeners

Vue 提供了一个 $listeners property,它是一个对象,里面包含了作用在这个组件上的所有监听器。

{ focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },}

有了这个 $listeners property,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。

<script>
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> `
})
</script>

现在 <base-input> 组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 <input> 元素一样使用了:所有跟它相同的 attribute 和监听器都可以工作,不必再使用 .native 监听器。

.sync修饰符

<!--comp: 对其赋新值-->
<script>
Vue.compontent('text-document',{
...
this.$emit('update:title', newTitle)
...
})
</script>
<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>

注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。

v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的

最新文章

  1. 1280*720P和1920*1080P的视频在25帧30帧50帧60帧时的参数
  2. 加密狗的管理层API(C#代码)
  3. 大熊君JavaScript插件化开发------(第一季)
  4. Struts2环境搭建
  5. 源码方式安装mysql5.5
  6. mac安装最新版本的git
  7. vasprintf的实现
  8. CodeIgniter网站静态化管理系统
  9. stdafx.h的作用以及原理
  10. 以编程方式使用 Word 中的内置对话框
  11. Win10使用小技巧
  12. css实现超连接按钮形式显示
  13. 莱特币ltc在linux下的多种挖矿方案详解
  14. CentOS 7.0 安装配置 kafka 消息队列
  15. Cesium 一个导致浏览器内存一直增长的方法
  16. springmvc的介绍和第一个例子
  17. [Alpha阶段]第七次Scrum Meeting
  18. Windows 10 关闭Hyper-V
  19. Elasticsearch index fields 重命名
  20. Django的学习(六)————templates过滤器、Django shell、admin

热门文章

  1. [图像处理] YUV图像处理入门2
  2. [OpenCV实战]47 基于OpenCV实现视觉显著性检测
  3. Docker搭建Cloudreve网盘
  4. python之路25 面向对象 封装(隐藏、伪装)、多态、反射
  5. 10分钟做好 Bootstrap Blazor 的表格组件导出 Excel/Word/Html/Pdf
  6. C语言写的 史上最公平的投票系统
  7. BBS登录与注册功能的总结
  8. P32_全局配置 - tabBar
  9. Zookeeper+SpringCloud微服务(入门二)
  10. Spring Boot学习笔记(一)----概要与入门