Node

vue component

2016-10-24  本文已影响3829人  lmem

1.入门

<div id="example">
  <my-component></my-component>
</div>
// register 全局
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
// create a root instance
new Vue({
  el: '#example'
})

结果

<div id="example">
     <div>A custom component!</div>
</div>

局部组件

var Child = {
  template: '<div>A custom component!</div>'
}
new Vue({
  // ...
  components: {
    // <my-component> will only be available in parent's template
    'my-component': Child
  }
})

2.陷阱

<ul>, <ol>, <table> and <select>
会有问题,会报错。应该用is
<table>
    <tr is="my-row"></tr>
</table>

以下三种不起作用
(1)<script type="text/x-template">
(2)JavaScript inline template strings
(3).vue components

3.data必须是function

<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>

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 {
                counter: 0
            }
  }
})
new Vue({
  el: '#example-2'
})
Paste_Image.png

4.父子组件 props

props down, events up. 父组件传递 data down to the child 通过 props, child sends messages to the parent via events.

Paste_Image.png
(1)props传值
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>'
})
<child message="hello!"></child>

(2)动态 props

<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
//简写形式
<child :my-message="parentMsg"></child>


<comp v-bind:some-prop="1"></comp>
传递的是数字1,非字符串
(3)Prop Validation

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
      }
    }
  }
})

当检查失败,会给个warining,type选项
String
Number
Boolean
Function
Object
Array

4.父子组件 event

父组件可以监听子组件的事件

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
Paste_Image.png

如果是原生事件+.native

<my-component v-on:click.native="doTheThing"></my-component>

**5.v-model 用于组件

<input v-model="something">
等价于
<input v-bind:value="something" v-on:input="something = $event.target.value">

//条件
accept a value prop
emit an input event with the new value

<div id="v-model-example">
  <p>{{ message }}</p>
  <my-input
    label="Message"
    v-model="message"
  ></my-input>
</div>
Vue.component('my-input', {
  template: '\
    <div class="form-group">\
      <label v-bind:for="randomId">{{ label }}:</label>\
      <input v-bind:id="randomId" v-bind:value="value" v-on:input="onInput">\
    </div>\
  ',
//1.必须有value
  props: ['value', 'label'],
  data: function () {
    return {
      randomId: 'input-' + Math.random()
    }
  },
  methods: {
    onInput: function (event) {
    //2.必须触发input
      this.$emit('input', event.target.value)
    }
  },
})
new Vue({
  el: '#v-model-example',
  data: {
    message: 'hello'
  }
})
Paste_Image.png

6.不是父子组件的交流

创建空的Vue对象

var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
  // ...
})

7.Single slot

父组件的内容会被删除,除非子组件中有多余一个的slot标签

Suppose we have a component called my-component with the following template:
<div>
  <h2>I'm the child title</h2>
  <slot>
    This will only be displayed if there is no content
    to be distributed.
  </slot>
</div>

And a parent that uses the component:
<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>

The rendered result will be:
<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>

8.Name slot

For example, suppose we have an app-layout component with the following template:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
Parent markup:

<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>
The rendered result will be:

<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>

9.动态组件

<component>元素绑定is属性

var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'home'
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})
<component v-bind:is="currentView">
  <!-- component changes when vm.currentView changes! -->
</component>
If you prefer, you can also bind directly to component objects:

var Home = {
  template: '<p>Welcome home!</p>'
}
var vm = new Vue({
  el: '#example',
  data: {
    currentView: Home
  }
})

如果要缓存所有组件

<keep-alive>
<component :is="currentView">
<!-- inactive components will be cached! -->
</component>
</keep-alive>

10.简写形式

<my-component
:foo="baz" //v-bind
:bar="qux"
@event-a="doThis" //v-on
@event-b="doThat"
>
<img slot="icon" src="...">
<p slot="main-text">Hello!</p>
</my-component>

11.获取子组件的引用ref

<div id="parent">
<user-profile ref="profile"></user-profile>
</div>

var parent = new Vue({ el: '#parent' })
// access child component instance
var child = parent.$refs.profile

12.X-template

<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>

Vue.component('hello-world', {
    template: '#hello-world-template'
})
上一篇下一篇

猜你喜欢

热点阅读