组件是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码,说白了就是一组可以重复使用的模板。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

可以把组件代码按照template、style、script的拆分方式,放置到对应的.vue文件中。
组件预定义选项中最核心的几个: 模板(template)、初始数据(data)、接受的外部参数(props)、方法(methods)、生命周期钩子函数(lifecycle hooks)。
Vue中有两种组件的注册类型:全局注册和局部注册。

全局注册

全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
<tagName></tagName>

全局组件示例:

<body>
<div id="app">
<!--组件的使用-->>
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script> //定义一个新组件
Vue.component('button-counter',{
data:function(){
return{
count:0
}
}, template:'<button @click="count++">点击了{{count}}次。</button>'
}) var app = new Vue({
el: "#app",
data: { }
});
</script> </body>

  

上面的示例代码,每个组件都会各自独立维护它的 “count”。因为每用一次组件,就会有一个它的新实例被创建。
注意:data 必须是一个函数。一个组件的 "data" 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立拷贝。如果 Vue 没有这条规则,在复用组件的时候,当一个组件的“data”发生改变时,就会影响其他实例。

局部注册

局部组件示例:

<body>
<div id="app">
<test-component></test-component> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script> var testComponent = Vue.extend({
template: '<span>局部组件示例!</span>'
}); var app = new Vue({
el: "#app",
components:{
'test-component':testComponent
}
});
</script> </body>

  

组件之间的数据传递

1. props 传递参数

props”是组件数据的一个字段,用来接受父组件传递过来的数据的一个自定义属性。因为组件实例的作用域是孤立的,所以子组件需要显式地用props选项来获取父组件的数据。 Props选项可以是字面量、表达式、绑定修饰符。
示例:

<body>
<div id="app">
<demo message="hello!"></demo> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script> //定义一个新组件
Vue.component('demo',{
//声明 props
props:['message'], template: '<span>{{ message }}</span>' }) var app = new Vue({
el: "#app"
});
</script> </body>

  动态props 示例:

<body>
<div id="app">
<demo2 v-bind:message="parentMsg"></demo2>
</div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script> Vue.component('demo2',{
props:['message'], template: '<span>{{ message }}</span>' }) var app = new Vue({
el: "#app",
data: {
parentMsg: '父组件内容'
}
});
</script> </body>

  上面的示例是用v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。

prop 是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来。如果子组件要把数据传递回去,就需要使用自定义事件!可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface)。
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
示例:

<body>
<div id="app">
<h2>{{ total }}</h2>
<hr>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
// data 必须是一个函数
//这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
}
},
}) var app = new Vue({
el: "#app",
data: {
total:0
},
methods:{
incrementTotal:function(){
this.total += 1
}
}
});
</script> </body>

2. 插槽slot 的方式  

Vue 实现了一套内容分发的 API,将 <slot> 元素作为承载分发内容的出口。 <slot> 元素作为承载分发内容的出口,作者称其为 插槽,可以应用在组合组件的场景中。
当组件渲染的时候,<slot></slot> 将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML。
如果 template 中没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。

示例:

<body>
    <div id="app">        
        <todo>
            <!-- 将值 通过插槽插入 -->>
            <todo-title slot="todo-title"  v-bind:title="todoTitle">  </todo-title>
            <todo-items slot="todo-items"
                v-for="(item, index) in todoItems"
                v-bind:item="item"
                v-bind:index="index":key="index"></todo-items>
            </todo-items>
        </todo>
      </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    <script>
       
        // 在模板中 留出插槽
        Vue.component('todo', {
        template: '<div>\
                    <div>待办事项</div>\
                    <slot name="todo-title"></slot>\
                    <ul>\
                        <slot name="todo-items"></slot>\
                    </ul>\
                   </div>'
        });
        //定义名为 todo-title 待办标题组件
        Vue.component('todo-title', {
            props: ['title'],
            template: '<div>{{title}}</div>'
        });
        //定义名为 todo-items 待办标题组件
        Vue.component('todo-items', {
            //这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
            props: ['index', 'item'],
            template: '<li>{{index + 1}}. {{item}}</li>',
        });
        var app = new Vue({
            el: "#app",            
            data: {
                //初始化数据
                todoTitle: 'Vue 笔记',
                todoItems: ['环境搭建', '基础知识', '示例'],
            }
        });
    </script>
   
</body>

最新文章

  1. 设计一个自动生成棋盘格子的JS小程序
  2. 字符串匹配--Karp-Rabin算法
  3. winrar 5.21去广告
  4. C#中Split分隔字符串的应用(C#、split、分隔、字符串)
  5. TEXT文本编辑框2
  6. 201421123042 《Java程序设计》第6周学习总结
  7. Android 8.1 源码_启动篇(一) -- 深入研究 init(转 Android 9.0 分析)
  8. python使用正则解析网络地址的各个部分
  9. 算法笔记--Splay &amp;&amp; Link-Cut-Tree
  10. IIS中配置访问HTTPS
  11. 用Pyinstaller 实现py.转化为exe可执行文件----二维码实例
  12. Python Django框架笔记(二):创建应用和django 管理
  13. Gitlab+Jenkins学习之路(二)之gitlab部署
  14. 机器学习之路: tensorflow 自定义 损失函数
  15. PHP多进程学习(二)__fork起多个子进程,父进程的阻塞与非阻塞
  16. 命令行创建2003的IP安全策略
  17. php7+apache2.4+mysql 环境配置(window环境)
  18. Delphi调用Java类
  19. 【leetcode刷题笔记】Edit Distance
  20. php总结5——常量、文件上传

热门文章

  1. 构建SpringCloud网关服务
  2. loadrunner11安装时提示缺少Microsoft Visual c++2005 sp1组件的解决办法
  3. 几种数据库jar包获取方式
  4. [OpenCV实战]49 对极几何与立体视觉初探
  5. [Untiy]贪吃蛇大作战(二)——规则界面
  6. 2023牛客寒假算法基础集训营1 ACDEFGHKLM
  7. oracle创建全文索引(oracle text)
  8. Redis之key的淘汰策略
  9. MySQL 索引的创建、删除
  10. 12.ThreadLocal的那点小秘密