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>
<!-- `picked` is a string "a" when checked --> <input type="radio" v-model="picked" value="a"> <!-- `toggle` is either true or false --> <input type="checkbox" v-model="toggle"> <!-- `selected` is a string "abc" when selected --> <select v-model="selected"> <option value="abc">ABC</option> </select>
<div id="example-2"> <!-- `greet` is the name of a method defined below --> <button v-on:click="greet">Greet</button> </div>
var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, // define methods under the `methods` object methods: { greet: function (event) { // `this` inside methods points to the Vue instance alert('Hello ' + this.name + '!') // `event` is the native DOM event alert(event.target.tagName) } } }) // you can invoke methods in JavaScript too example2.greet() // -> 'Hello Vue.js!'
<!-- the click event's propagation will be stopped --> <a v-on:click.stop="doThis"></a> <!-- the submit event will no longer reload the page --> <form v-on:submit.prevent="onSubmit"></form> <!-- modifiers can be chained --> <a v-on:click.stop.prevent="doThat"></a> <!-- just the modifier --> <form v-on:submit.prevent></form> <!-- use capture mode when adding the event listener --> <div v-on:click.capture="doThis">...</div> <!-- only trigger handler if event.target is the element itself --> <!-- i.e. not from a child element --> <div v-on:click.self="doThat">...</div>
Key修饰符
当监听键盘事件时,我们需要查看key code,Vue也为v-on提供了键盘事件的修饰符:
1 2
<!-- only call vm.submit() when the keyCode is 13 --> <input v-on:keyup.13="submit">
技术所有的key code是很难的,为此Vue提供了常用key code的别名:
1 2 3 4
<!-- same as above --> <input v-on:keyup.enter="submit"> <!-- also works for shorthand --> <input @keyup.enter="submit">
<script> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // a computed getter reversedMessage: function () { // `this` points to the vm instance return this.message.split('').reverse().join('') } } }) </script>
<!-- Since there is already a rich ecosystem of ajax libraries --> <!-- and collections of general-purpose utility methods, Vue core --> <!-- is able to remain small by not reinventing them. This also --> <!-- gives you the freedom to just use what you're familiar with. --> <script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script> <script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script> <script> var watchExampleVM = new Vue({ el: '#watch-example', data: { question: '', answer: 'I cannot give you an answer until you ask a question!' }, watch: { // whenever question changes, this function will run question: function (newQuestion) { this.answer = 'Waiting for you to stop typing...' this.getAnswer() } }, methods: { // _.debounce is a function provided by lodash to limit how // often a particularly expensive operation can be run. // In this case, we want to limit how often we access // yesno.wtf/api, waiting until the user has completely // finished typing before making the ajax request. To learn // more about the _.debounce function (and its cousin // _.throttle), visit: https://lodash.com/docs#debounce getAnswer: _.debounce( function () { var vm = this if (this.question.indexOf('?') === -1) { vm.answer = 'Questions usually contain a question mark. ;-)' return } vm.answer = 'Thinking...' axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) }, // This is the number of milliseconds we wait for the // user to stop typing. 500 ) } }) </script>
在这个场景中,使用watch选项允许我们执行异步操作,限制多久执行操作,以及只有获取到数据 才设置state。而这些在属性计算都是不可用的。除了这个选项你还可以使用必要的vm.$watch API
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id"></div>
这样绑定的限制是,在双花括号语法中只能使用一个表达式:
1 2 3 4
<!-- this is a statement, not an expression: --> {{ var a = 1 }} <!-- flow control won't work either, use ternary expressions --> {{ if (ok) { return message } }}
FROM ubuntu:12.04 RUN apt-get update && apt-get install -y python python-pip curl RUN curl -sSL https://github.com/shykes/helloflask/archive/master.tar.gz | tar -xzv RUN cd helloflask-master && pip install -r requirements.txt