Vue 基础学习(3):组件注册、组件间数据交互、组件插槽

1、组件注册

1.1 全局组件注册语法及组件用法

(1)全局组件注册语法

Vue.component(组件名称, {
	data: 组件数据,
	template: 组件模板内容
})

其中,组件数据必须是一个函数,最后必须返回一个对象
 // 注册一个名为 button-counter 的新组件
 Vue.component('button-counter', {
     data: function () {
         return {
             count: 0
         }
     },
     template: '<button @click="handle">点击了{{count}}次</button>',
     methods: {
         handle: function () {
             this.count += 2;
         }
     }
 });

(2)组件用法

 <div id="app">
     <!-- 组件的使用 -->
     <button-counter></button-counter>
     <button-counter></button-counter>
     <button-counter></button-counter>
 </div>

1.2 组件注册注意事项

(1)data 必须是一个函数

因为 vue 的组件可能会在不同的页面中被调用,是一个函数的话,每一次调用就会执行 data 函数并返回新的数据,这样就可以避免多处调用之间的数据污染

  1. 一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。
  2. 如果 data 是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间 data 不冲突,data 必须是一个函数。

(2)组件模板内容必须是单个根元素

(3)组件模板内容可以是模板字符串

  • 模板字符串需要浏览器提供支持(ES6语法)

(4)组件命名方式

  • 短横线方式 :Vue.component('my-component', { /* ... */ })
  • 驼峰方式:Vue.component('MyComponent', { /* ... */ })
  • 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件。
<div id="app">
    <!-- 在普通的标签模板中,不区分大小写 -->
    <!-- 2.组件的使用 -->
    <Hello-World></Hello-World>
</div>

 Vue.component('HelloWorld', {
     data: function () {
         return {
             msg: 'Hello World!'
         }
     },
     template: '<div>{{msg}}</div>'
 });

1.3 局部组件注册

局部组件只能在注册他的父组件中使用。

语法:

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

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

例子:

<div id="app">
    <!-- 组件的使用 -->
    <hello-world></hello-world>
    <hello-tom></hello-tom>
    <hello-jerry></hello-jerry>
    <test-com></test-com>
</div>
<script src="js/vue.js"></script>
<script>
    // 全局组件注册
    Vue.component('test-com', {
        data: function () {
            return {
                abc: 'abc'
            }
        },
        template: '<div>Test{{abc}}<hello-world></hello-world></div>'
    });
    // 局部组件注册
    // 局部组件只能在注册他的父组件中使用
    var HelloWorld = {
        data: function () {
            return {
                msg: 'Hello World!'
            }
        },
        template: '<div>{{msg}}</div>'
    };
    var HelloTom = {
        data: function () {
            return {
                msg: 'Hello Tom!'
            }
        },
        template: '<div>{{msg}}</div>'
    };
    var HelloJerry = {
        data: function () {
            return {
                msg: 'Hello Jerry!'
            }
        },
        template: '<div>{{msg}}</div>'
    };
    var vm = new Vue({
        el: '#app',
        data: {
        },
        components: {
            'hello-world': HelloWorld,
            'hello-tom': HelloTom,
            'hello-jerry': HelloJerry
        }
    });
</script>

2、组件间数据交互

组件之间共享数据的方式

  • 父向子传值:v-bind 属性绑定
  • 子向父传值:v-on 事件绑定
  • 兄弟组件之间共享数据: EventBus
    • $on 接收数据的那个组件
    • $emit 发送数据的那个组件

2.1 父组件向子组件传值

(1)组件内部通过 props 接收传递过来的值

Vue.component(‘menu-item', {
	props: ['title'],
	template: '<div>{{ title }}</div>'
})

(2)父组件通过属性将值传递给子组件

<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>

例子:

<div id="app">
    <div>{{pmsg}}</div>
    <menu-item title="来自父组件的值"></menu-item>
    <menu-item :title='ptitle' content='hello'></menu-item>
</div>
<script src="js/vue.js"></script>
<script>
    // 父组件向子组件传值-基本使用
    // 子组件注册
    Vue.component('menu-item', {
        props: ['title', 'content'],
        data: function () {
            return {
                msg: '子组件本身的数据'
            }
        },
        template: '<div>{{msg + "----" + title + "----" + content}}</div>'
    })
    var vm = new Vue({
        el: '#app',
        data: {
            pmsg: '父组件中的内容',
            ptitle: '动态绑定属性'
        }
    });
</script>

效果:
在这里插入图片描述

(3)props 属性名规则

  • 在 props 中使用驼峰形式,模板中需要使用短横线的形式。
  • 字符串形式的模板中没有这个限制。
Vue.component(‘menu-item', {
	// 在 JavaScript 中是驼峰式的
	props: [‘menuTitle'],
	template: '<div>{{ menuTitle }}</div>'
})

<!– 在html中是短横线方式的 -->
<menu-item menu-title=“nihao"></menu-item>

(4)props 属性值类型

  • 字符串 String
  • 数值 Number
  • 布尔值 Boolean
  • 数组 Array
  • 对象 Object

2.2 子组件向父组件传值

(1)子组件通过自定义事件向父组件传递信息

<button v-on:click='$emit("enlarge-text") '>扩大字体</button>
<button v-on:click='$emit("enlarge-text", 0.1) '>扩大字体</button>

(2)父组件监听子组件的事件

<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
<menu-item v-on:enlarge-text='fontSize += $event'></menu-item>

例子:

 <div id="app">
     <div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
     <!-- 父组件通过属性将值传递给子组件 -->
     <!-- 父组件监听子组件的事件 -->
     <menu-item :parr='parr' v-on:enlarge-text='handle($event)'></menu-item>
 </div>
 <script src="js/vue.js"></script>
 <script>
     // 子组件向父组件传值 - 携带参数
     // props传递数据原则:单向数据流
     Vue.component('menu-item', {
         // 组件内部通过props接收传递过来的值
         props: ['parr'],
         template: `
         <div>
             <ul>
                 <li :key='index' v-for='(item, index) in parr'>{{item}}</li>
             </ul>
             <!-- 子组件通过自定义事件向父组件传递信息 -->
             <button @click='$emit("enlarge-text", 5)'>扩大父组件中字体大小</button>
             <button @click='$emit("enlarge-text", 10)'>扩大父组件中字体大小</button>
         </div>
         `
     });
     var vm = new Vue({
         el: '#app',
         data: {
             pmsg: '父组件中内容',
             parr: ['apple', 'orange', 'banana'],
             fontSize: 10
         },
         methods: {
             handle: function (val) {
                 // 扩大字体大小
                 this.fontSize += val;
             }
         }
     });
 </script>

效果:
在这里插入图片描述

2.3 非父子组件间传值

(1)单独的事件中心管理组件间的通信

var eventHub = new Vue()

(2)监听事件与销毁事件

eventHub.$on('add-todo', addTodo)
eventHub.$off('add-todo')

(3)触发事件

eventHub.$emit(‘add-todo', id)

在这里插入图片描述
例子:

<div id="app">
    <div>父组件</div>
    <div>
        <button @click='handle'>销毁事件</button>
    </div>
    <test-tom></test-tom>
    <test-jerry></test-jerry>
</div>
<script src="js/vue.js"></script>
<script>
    // 兄弟组件之间数据传递
    // 单独的事件中心管理组件间的通信
    var hub = new Vue();
    Vue.component('test-tom', {
        data: function () {
            return {
                num: 0
            }
        },
        template: `
        <div>
            <div>TOM:{{num}}</div>
            <div>
                <button @click='handle'>点击</button>
            </div>
        </div>
        `,
        methods: {
            handle: function () {
                // 触发兄弟组件的事件
                hub.$emit('jerry-event', 2);
            }
        },
        mounted: function () {
            // 监听事件
            hub.$on('tom-event', (val) => {
                this.num += val;
            });
        }
    });
    Vue.component('test-jerry', {
        data: function () {
            return {
                num: 0
            }
        },
        template: `
        <div>
            <div>JERRY:{{num}}</div>
            <div>
                <button @click='handle'>点击</button>
            </div>
        </div>
        `,
        methods: {
            handle: function () {
                // 触发兄弟组件的事件
                hub.$emit('tom-event', 1);
            }
        },
        mounted: function () {
            // 监听事件
            hub.$on('jerry-event', (val) => {
                this.num += val;
            });
        }
    });
    var vm = new Vue({
        el: '#app',
        data: {
        },
        methods: {
            handle: function () {
                // 销毁事件
                hub.$off('tom-event');
                hub.$off('jerry-event');
            }
        }
    });
</script>

效果:
在这里插入图片描述

3、组件插槽

3.1 组件插槽的作用

父组件向子组件传递内容。

在这里插入图片描述

3.2 组件插槽基本用法

(1)插槽位置

Vue.component('alert-box', {
	template: `
		<div class="demo-alert-box">
			<strong>Error!</strong>
			<slot></slot>
		</div>
	`
})

(2)插槽内容

<alert-box>Something bad happened.</alert-box>

例子:

<div id="app">
    <alert-box>有bug发生</alert-box>
    <alert-box>有一个警告</alert-box>
    <alert-box></alert-box>
</div>
<script src="js/vue.js"></script>
<script>
    // 组件插槽:父组件向子组件传递内容
    Vue.component('alert-box', {
        template: `
        <div>
            <strong>ERROR</strong>
            <slot>默认内容</slot>
        </div>
        `
    });
    var vm = new Vue({
        el: '#app',
        data: {
        }
    });
</script>

效果:
在这里插入图片描述

3.3 具名插槽用法

在这里插入图片描述

(1)插槽定义

 // 具名插槽
 Vue.component('base-layout', {
     template: `
     <div>
         <header>
             <slot name='header'></slot>
         </header>
         <main>
             <slot></slot>
         </main>
         <footer>
             <slot name='footer'></slot>
         </footer>
     </div>
     `
 });

(2)插槽内容

 <div id="app">
     <base-layout>
    	<h3 slot="header">标题1</h3>
   		 <p>主要内容</p>
    	<p slot="footer">底部信息</p>
     </base-layout>
 </div>

3.4 作用域插槽

应用场景:父组件对子组件的内容进行加工处理

在这里插入图片描述
例子:

<div id="app">
    <!-- 插槽内容 -->
    <!-- 父组件通过属性list向子组件传递值 -->
    <fruit-list :list='list'>
        <template slot-scope='slotProps'>
            <strong v-if='slotProps.info.id == 3' class="current">{{slotProps.info.name}}</strong>
            <span v-else>{{slotProps.info.name}}</span>
        </template>
    </fruit-list>
</div>
<script src="js/vue.js"></script>
<script>
    // 作用域插槽
    // 应用场景:父组件对子组件的内容进行加工处理
    Vue.component('fruit-list', {
        props: ['list'],
        // 插槽定义 
        template: `
        <div>
            <li v-bind:key='item.id' v-for='item in list'>
                <slot v-bind:info='item'>{{item.name}}</slot>
            </li>
        </div>
        `
    });
    var vm = new Vue({
        el: '#app',
        data: {
            list: [{
                id: 1,
                name: 'apple'
            }, {
                id: 2,
                name: 'orange'
            }, {
                id: 3,
                name: 'banana'
            }]
        }
    });
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值