var Child = { template: '<div>A custom component!</div>' } new Vue({ // ... components: { // <my-component> will only be available in parent's template 'my-component': Child } })
var data = { counter: 0 } Vue.component('simple-counter', { template: '<button v-on:click="counter += 1">{{ counter }}</button>', // data is technically a function, so Vue won't // complain, but we return the same object // reference for each component instance data: function () { return data } }) new Vue({ el: '#example-2' })
Vue.component('child', { // declare the props props: ['message'], // just like data, the prop can be used inside templates // and is also made available in the vm as this.message template: '<span>{{ message }}</span>' })
Vue.component('example', { props: { // basic type check (`null` means accept any type) propA: Number, // multiple possible types propB: [String, Number], // a required string propC: { type: String, required: true }, // a number with default value propD: { type: Number, default: 100 }, // object/array defaults should be returned from a // factory function propE: { type: Object, default: function () { return { message: 'hello' } } }, // custom validator function propF: { validator: function (value) { return value > 10 } } } })
Vue.component('currency-input', { template: '\ <span>\ $\ <input\ ref="input"\ v-bind:value="value"\ v-on:input="updateValue($event.target.value)"\ >\ </span>\ ', props: ['value'], methods: { // Instead of updating the value directly, this // method is used to format and place constraints // on the input's value updateValue: function (value) { var formattedValue = value // Remove whitespace on either side .trim() // Shorten to 2 decimal places .slice(0, value.indexOf('.') + 3) // If the value was not already normalized, // manually override it to conform if (formattedValue !== value) { this.$refs.input.value = formattedValue } // Emit the number value through the input event this.$emit('input', Number(formattedValue)) } } })
Vue.component('child-component', { // this does work, because we are in the right scope template: '<div v-show="someChildProperty">Child</div>', data: function () { return { someChildProperty: true } } })
<div> <h2>I'm the child title</h2> <slot> This will only be displayed if there is no content to be distributed. </slot> </div>
当一个父组件使用它时:
1 2 3 4 5 6 7
<div> <h1>I'm the parent title</h1> <my-component> <p>This is some original content</p> <p>This is some more original content</p> </my-component> </div>
渲染结果是:
1 2 3 4 5 6 7 8
<div> <h1>I'm the parent title</h1> <div> <h2>I'm the child title</h2> <p>This is some original content</p> <p>This is some more original content</p> </div> </div>
<app-layout> <h1 slot="header">Here might be a page title</h1> <p>A paragraph for the main content.</p> <p>And another one.</p> <p slot="footer">Here's some contact info</p> </app-layout>
渲染的结果是:
1 2 3 4 5 6 7 8 9 10 11 12
<div class="container"> <header> <h1>Here might be a page title</h1> </header> <main> <p>A paragraph for the main content.</p> <p>And another one.</p> </main> <footer> <p>Here's some contact info</p> </footer> </div>
<div class="parent"> <div class="child"> <span>hello from parent</span> <span>hello from child</span> </div> </div>
列表中如何使用slot呢?
1 2 3 4 5 6
<my-awesome-list :items="items"> <!-- scoped slot can be named too --> <template slot="item" scope="props"> <li class="my-fancy-item">{{ props.text }}</li> </template> </my-awesome-list>
list组件模板:
1 2 3 4 5 6 7
<ul> <slot name="item" v-for="item in items" :text="item.text"> <!-- fallback content here --> </slot> </ul>
Vue.component('async-webpack-example', function (resolve) { // This special require syntax will instruct Webpack to // automatically split your built code into bundles which // are loaded over Ajax requests. require(['./my-async-component'], resolve) })
// in a component definition components: { // register using kebab-case 'kebab-cased-component': { /* ... */ }, // register using camelCase 'camelCasedComponent': { /* ... */ }, // register using TitleCase 'TitleCasedComponent': { /* ... */ } }
在html的模板,需要使用-分界符命名规则:
1 2 3 4
<!-- alway use kebab-case in HTML templates --> <kebab-cased-component></kebab-cased-component> <camel-cased-component></camel-cased-component> <title-cased-component></title-cased-component>
在字符串模板中也没有什么限制:
1 2 3 4
<!-- use whatever you want in string templates! --> <my-component></my-component> <myComponent></myComponent> <MyComponent></MyComponent>