Vue.js组件
组件的基本使用
前端组件化开发是现在前端框架中一个非常重要的思想,对页面内容进行拆分过后,便可独立维护,可复用性大大提高了。哪里出现问题,直接去修改对应的组件即可。
全局组件
全局注册的组件可以在任何一个div中使用该组件
局部组件
在实例选项中注册组件,这个组件只能在这个实例中使用
组件中的data
组件中的data不是一个对象,而是一个函数。这样的好处在于每个实例可以维护一份被返回对象的独立副本。如果data是一个对象,则会影响到其他实例,因为js对象是引用类型的,return外部对象是会被共享的。所以,需要为每个组件返回一个新的对象。
使用template元素创建组件
直接将组件内的元素写在<template></template>
标签内,符合编写HTML标签的习惯,使代码阅读性更强。
组件嵌套
组件嵌套是指把组件与组件嵌套在一起,在父组件下的模板中,以标签的形式调用子组件。
使用props传递数据
- props的值是字符串数组
- props的值是对象
组件通信
组件实例的作用域是相互独立的,这就意味着不同组件之间无法相互引用。组件间的通信包括3种情况: 父组件向子组件通信;子组件向父组件通信;非父子组件之间的通信。
父组件向子组件通信
通过props实现,在子组件标签章添加子组件props中创建的属性,把需要传递给子组件的值赋值给该属性。
如果传递的数据不是静态数据,可以使用v-bind
指令来动态地绑定props的值。当父组件的数据变化时,这种变化会传递给子组件。
父级props的更新会向下流动到子组件中,但是子组件的更新不会影响父级props。这样会防止子组件意外改变父组件的状态,从而导致应用的数据流向难以理解。
子组件向父组件通信
当子组件需要向父组件传递数据时,就要用到自定义事件。v-on
指令除了监听DOM事件之外,还可以用于组件之间的自定义事件。子组件通过$emit
来触发事件,父组件在子组件的自定义标签上使用v-on
指令来监听子组件触发的自定义事件。
非父子组件之前的通信
非父子组件之前通信时,需要引入一个Vue实例bus作为媒介,通过bus触发事件和监听事件来实现组件之前的通信和参数传递,类似于子组件向父组件通信,但是利用了一个新的Vue实例作为媒介,而不是以当前Vue实例作为媒介。
创建自定义组件
一般来说,就是有组件嵌套的。然后可以在全局和局部都注册该组件。父组件main-work中使用了子组件main-work-list, 并实现了组件间的通信。父组件将值下发给子组件,子组件使用v-for
指令将列表显示出来,只要改变父组件的值,子组件中的列表值就会发生改变。当使用$emit()
触发事件实现选择子组件的列表项时,该列表项的值便可以传递给父组件
通过我的观察发现,父组件中套用子组件,子组件在使用
$emit
向父组件传递数据的时候,一般都是触发的父组件中的函数或者是将父组件中实现的函数绑定在子组件的事件中。
内容分发
使用<slot>
标签作为承载分发内容的出口,当需要混合父组件的内容和子组件的模板时,就会用到slot
。换句话说就是当组件的内容由父组件决定时,就会使用slot
。
emmmm….从效果的角度上面讲,和父组件传递数据到子组件是一样的,但是从代码的角度上面看的话,内容分发要简洁很多。
单个插槽
在子组件中使用特殊的slot
元素就可以为这个子组件开启一个slot
。父组件模板中,插入在子组件标签内的所有内容将代替子组件的slot
标签和内容。
具名插槽
如果一个组件中有多个部分的内容是动态的,则需要为slot
元素指定一个name属性,具有name属性的插槽称为具名插槽。具名插槽可以分发多个内容,也可以与单个插槽共存。
作用域插槽
使用slot
元素后,子组件可向父组件传递数据,从而实现与父级的通信。Vue还提供了另外一种通信方式。在父级中,具有特殊属性scope
的template
元素被称为作用域插槽模板。scope
的值对应一个临时变量名,此变量用于接受从子组件中传递的props对象。
这个例子不是很好理解,所以我把代码和效果贴上来了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h3>作用域插槽</h3>
<div id="app">
<my-component>
<template scope="myProps">
<p><span style="color:read;">{{myProps.text}}</span></p>
</template>
</my-component>
</div>
<script src="../../js/vue.js"" type=" text/javascript" charset="utf-8"></script>
<script type="text/javascript">
Vue.component('my-component', {
template: `
<div class="container">
<slot text="hello from child"></slot>
</div>
`,
})
new Vue({
el: '#app'
})
</script>
</body>
</html>
在上述代码中,slot元素的text属性被赋值为hello from child,在父组件中使用了作用域插槽模板,在template中使用了scope属性对应的变量myProps接受子组件数据,并通过,将子组件的数据显示出来
作用域插槽2
要是把这部分的template的部分注释掉的话,网页中就显示不出来之前的内容了
因为slot本身是要父组件把内容分发给子组件的,这个temlpate的过程就相当于是
- 先利用props将数据传递给子组件
- 再利用scope把子组件中的props传递给父组件
- 最后在template中将内容分发给子组件
至于这里面的循环是怎么实现的我就不是很清楚了
动态组件
通过使用保留的componet元素动态地绑定到其is特性上,可以使多个组件匹配到一个挂载点,并动态进行切换。简直就是天然的Tab标签页面之间的转换。