vue组件(一)——组件介绍

定义

组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el这样根实例特有的选项。

全局组件

我们知道,可以通过以下方式创建一个Vue实例:

new Vue({
    el:"#app",
    //选项
})


要注册一个全局组件,可以使用 Vue.component(tagName, options)。例:

Vue.component('my-component',{
    //选项
})

组件在注册之后,便可以作为自定义元素 <my-component></my-component> 在一个实例的模板中使用。注意确保在初始化根实例之前注册组件:

<div id="app">	
    <!-----引用组件----->	
    <my-component></my-component>
</div> 
<script>
// 注册
Vue.component('my-component', {  
    template: '<h3>我是全局组件!</h3>'
})
// 创建根实例
new Vue({  
    el: '#app'
})
</script>

全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

局部组件

你不必把每个组件都注册到全局。你可以通过某个 Vue 实例/组件的实例选项 components注册仅在其作用域中可用的组件:


<div id="app">
	<!-----引用组件----->
	<my-component></my-component>
</div>

<script>
var Child = {
    template: '<h3>我是局部组件!</h3>'
}
new Vue({ 
    el:"#app", 
    components: { 
        // <my-component> 将只在父组件模板中可用 
        'my-component': Child 
    }
})
</script>

你也可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。

注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:

var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'component-a': ComponentA
  },
  // ...
}

或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  },
  // ...
}

注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

  • 用在模板中的自定义元素的名称
  • 包含了这个组件选项的变量名

解析DOM模板时的注意事项

有些 HTML 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。

这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

<table>
  <blog-post-row></blog-post-row>
</table>

这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:

<table>
  <tr is="blog-post-row"></tr>
</table>

需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在

因此,请尽可能使用字符串模板。
上面的意思是下面的例子是会不行的:

<div id="app">
    <select>
        <optioncomp></optioncomp>
    </select>
</div>
<script>
    new Vue({
        el: '#app',
        components:{
            'optioncomp':{
                template: '<option >a</option>'
            }
        }
    })
</script>

但是用is特殊属性可以:

<div id="app">
    <select>
        <option is="optioncomp"></option>
    </select>
</div>

<script>

new Vue({
    el: '#app',
        components:{
            'optioncomp':{
                template: '<option >a</option>'
            }
        }
    })
</script>

或者temp模板标签也可以:

<div id="app">
    <select>
        <option is="optioncomp"></option>
    </select>
<!--模板内容存放区域-->
<script type="x-template" id="optioncompTemp">
    <option>a</option>
</script>
</div>

<script> 
    new Vue({ 
        el: '#app',
        components:{
            'optioncomp':{ template: '#optioncompTemp' } 
        } 
    }) 
</script>

或者内联模板字符串也行

<div id="app">
    <selectcomp></selectcomp>
</div>

<script>
    Vue.component('optioncomp',
        { template: '<option >a</option>' });
     new Vue({ 
        el: '#app',
        components:{ 
            'selectcomp':{
                template: ' <select><optioncomp></optioncomp></select>' 
             } 
        } 
    }) 
</script>

data必须是函数

构造 Vue 实例时传入的各种选项大多数都可以在组件里使用。只有一个例外:data 必须是函数。因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

如果 Vue 没有这条规则,点击一个按钮就可能会像如下代码一样影响到其它所有实例

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

由于这三个组件实例共享了同一个 data 对象,因此递增一个 counter 会影响所有组件!我们可以通过为每个组件返回全新的数据对象来修复这个问题:

data: function () {
  return {
    count: 0
  }
}

注意当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。

猜你喜欢

转载自blog.csdn.net/dd1145322563/article/details/82869427