赞
踩
// 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { // 1.data为一个函数,各个按钮的count是互相独立的 data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' }) Vue.component('button-counter', { // 2.data为一个对象,点击第一个按钮,其余按钮的count也会随之变化 data: { count: 0 }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
<!-- 3.多次使用同一个组件 -->
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
Vue.component('my-component-name', {
// ... options ...
})
Vue.component('my-component-name', { /* ... */ })
<my-component-name></my-component-name>
在开发中,通常会创建一个components目录用于专门放置组件,在该目录下,通常将每个组件放置在其各自的文件夹中。若某个组件需要使用其他组件,通常使用import / require模块系统.
// 导入组件
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
// 在模块系统中局部注册
export default {
components: {
ComponentA,
ComponentC
},
// ...
}
某些组件是相对通用的,会被作为基础组件,在各个组件中被频繁使用,会导致很多组件里都会有一个包含基础组件的长列表:
import BaseButton from './BaseButton.vue'
import BaseIcon from './BaseIcon.vue'
import BaseInput from './BaseInput.vue'
export default {
components: {
BaseButton,
BaseIcon,
BaseInput
}
}
<BaseInput
v-model="searchText"
@keydown.enter="search"
/>
<BaseButton @click="search">
<BaseIcon name="search"/>
</BaseButton>
因此,若使用了webpack(或在内部使用了webpack的Vue cli 3+),就可以考虑在应用入口文件(src/main.js)中全局导入基础组件(全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生):
import Vue from 'vue' import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase' // 参数:组件目录的相对路径,是否查询其子目录,匹配基础组件文件名的正则表达式 const requireComponent = require.context('./components',false,/Base[A-Z]\w+\.(vue|js)$/) // 遍历components目录下的文件 requireComponent.keys().forEach(fileName => { const componentConfig = requireComponent(fileName) // 获取组件配置 // 先获取和目录深度无关的文件名,再获取组件的 PascalCase 命名 const componentName = upperFirst(camelCase(fileName.split('/').pop().replace(/\.\w+$/, ''))) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 componentConfig.default || componentConfig ) })
// 1.注册子组件
Vue.component('blog-post', {
// 2.接收父组件参数
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
<!-- 3.在父组件中使用 -->
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
// 1.注册子组件
Vue.component('blog-post', {
// 2.接收父组件参数
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
<!-- 3.在父组件中使用 -->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
// 1.子组件定义
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
//通过$emit向父组件提交事件
<button v-on:click="$emit('enlarge-text',0.1)">Enlarge text</button>
<div v-html="post.content"></div>
</div>
`
})
<!-- 2.父组件 -->
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<!-- 通过v-on监听子组件提交的事件和数据 -->
<blog-post
v-for="post in posts" v-bind:key="post.id"
v-bind:post="post" v-on:enlarge-text="onEnlargeText"
v-on:enlarge-text="postFontSize += 0.1">
</blog-post>
</div>
</div>
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
},
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
})
<input v-model="searchText">
<!-- 等价于 -->
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
<!-- 用在组件上 -->
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event">
</custom-input>
<!-- 等价于 -- >
<custom-input v-model="searchText"></custom-input>
Vue.component('custom-input', {
props: ['value'],
template: `<input v-bind:value="value" v-on:input="$emit('input', $event.target.value)">`
})
<component v-bind:is="currentTabComponent"></component>
<!-- 自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,
并导致最终渲染结果出错 -->
<table>
<blog-post-row></blog-post-row>
</table>
<!-- 使用is -->
<table>
<tr is="blog-post-row"></tr>
</table>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。