0
点赞
收藏
分享

微信扫一扫

Vue 学习笔记 —— 组件化开发 (三)

at小涛 2022-02-10 阅读 49



Vue 组件化开发


  • ​​一、组件注册​​

  • ​​1.1 全局组件​​
  • ​​1.2 局部组件​​
  • ​​1.3 组件注册基本注意事项​​
  • ​​1.4 props 属性值类型​​

  • ​​二、组件之间数据交互​​

  • ​​2.1 父组件向子组件传递数据​​
  • ​​2.2 子组件向父组件传递数据​​
  • ​​2.3 子组件通过自定义事件向父组件传递信息​​
  • ​​2.4 非父子组件间传值 (兄弟组件之间数据交互)​​
  • ​​2.5 组件插槽​​
  • ​​2.6 具名插槽​​
  • ​​2.7 作用域插槽​​



案例式驱动,每个案例一个小例子,带领大家领略

一、组件注册

1.1 全局组件

基本语法:

<script>
Vue.component('组件名称', {
data: '组件数据',
template: '组件模板内容(HTML 标签)'
})
</script>

示例:


我们以一个点击按钮数据累加计算来演示组件的使用


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>组件化开发</title>
</head>
<body>
<div id="app">
<!-- 每个组件的都是相互独立的 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>

<script src="../vue.js"></script>
<script>
// Vue.component('button-counter' 两种方式
Vue.component('ButtonCounter', {
// 使用函数,形成一个闭包的环境,保证每个数据都是独立的。
data() {
return {
count: 0
}
},
// template: '<button v-on:click="count++">点击了{{count}}次</button>',
template: '<button @click="handle">点击了{{count}}次</button>',
methods: {
handle: function() {
this.count++;
},
}
})
var app = new Vue({
el: "#app",
data: {

}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_组件化

1.2 局部组件

我们在 Vue 实例中添加 components 属性,在这里我们就可以自定义自己的局部组件,使用方式和全局组件的差别不大

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>局部组件化开发</title>
</head>
<body>
<div id="app">
<component-a></component-a>
</div>
<!--
局部组件注册
局部组件只能在注册他的父组件中使用
-->
<script src="../vue.js"></script>
<script>
let ComponetA = {
data() {
return {
msg: 'Hello World'
}
},
template: '<div>{{msg}}</div>',
methods: {

}
}

var app = new Vue({
el:"#app",
data:{

},
components: {
'component-a': ComponetA
}
})
</script>
</body>
</html>

演示效果

Vue 学习笔记 —— 组件化开发 (三)_数据_02

1.3 组件注册基本注意事项

注册基本事项:


  1. data 必须是一个函数
  2. 组件模板内容必须是单个根元素
  3. 组件模板内容可以是模板字符串 ES6语法
  4. 如果使用驼峰式命名组件,要么在使用组件得时候,只能在字符串模板中用驼峰得方式使用组件

但是在普通得模板标签中,必须使用横线的方式使用组件

1.4 props 属性值类型


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

二、组件之间数据交互

2.1 父组件向子组件传递数据


  • 父组件向子组件传递数据,分为静态数据 和 动态数据(属性绑定实现)
  • 子组件接收父组件传递过来的内容,要通过 props 来接收父组件的数据

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>组件数据传递</title>
</head>
<body>
<div id="app">
<!--
1. 组件内部通过 props 接收传递过来的值
2. 父组件通过属性传值给子组件
3. props 属性名规则
在 props 中使用驼峰形式,模板中需要使用短横线的形式
字符串形式的模板中没有这个限制
-->
<h3>父组件向子组件传递数据</h3>
<div>
{{pmsg}}
</div>
<!-- 父组件向子组件传递数据 -->

<h3>二、静态数据传递</h3>
<!-- 静态传递 -->
<menu-item title="来自父组件的值"></menu-item>

<h3>三、动态数据传递</h3>
<!-- 动态传递 -->
<menu-item :title="ptitle"></menu-item>

<menu-item :title="pmsg" content="hello"></menu-item>

<h3>四、短横线绑定</h3>
<!-- 属性名称规则 短横线 -->
<my-menu menu-title="Hello"></my-menu>

<!-- 数组 -->
<h3>五、数组传递</h3>
<my-array :arr="parray"></my-array>

<h3>六、对象传递</h3>
<my-obj :person="person"></my-obj>
</div>

<script src="../vue.js"></script>
<script type="text/javascript">
Vue.component('menu-item', {
// props 接收父组件传过来的内容
props: ['title', 'content'],
data() {
return {
msg: '子组件本身的数据'
}
},
template: '<div>{{msg + "----" + title + "------" + content}}</div>'
});

Vue.component('my-menu', {
props: ['menuTitle'],
template: '<div>{{menuTitle}}</div>'
});

// 遍历数组
Vue.component('my-array', {
props: ['arr'],
template: '<ul><li v-for="(item,index) of arr" :key="index">{{item}}</li></ul>'
});

Vue.component('my-obj', {
props: ['person'],
template: '<div>{{person.name}} {{person.age}}</div>'
})
var app = new Vue({
el:"#app",
data:{
pmsg: '父组件的内容',
ptitle: '动态绑定属性',
parray: ['apple','orange','banana'],
person: {
name: 'coco',
age: 18
}
}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_插槽_03

2.2 子组件向父组件传递数据

子组件向父组件传值

props 传递数据原则,单向数据流


  1. 子组件通过自定义事件向父组件传递信息 $emit 向父组件传递数据
  2. 父组件监听子组件的事件

接下来我们以一个改变字体大小 以及 传递数组的实例来给给大家演示子组件向父最贱传递数据的流程

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>子组件向父组件传递数据</title>
</head>
<body>

<div id="app">
<!-- style 属性绑定 -->
<div :style="{fontSize: fontSize + 'px'}">{{pmsg}}</div>
<!-- 这个监听事件的名称必须和子组件的事件完全一致 -->
<menu-item :parr="parr" @enlarge-text="handle"></menu-item>
</div>

<script src="../vue.js"></script>
<script>
// 子组件向父组件传值 —— 基本用法
Vue.component('menu-item', {
props: ['parr'],
template:`
<div>
<ul>
<li :key="index" v-for="(item, index) of parr">{{item}}</li>
</ul>
<button @click="parr.push('lemon')">点击</button>
<button @click="$emit('enlarge-text')">扩大父组件中字体大小</button>
</div>
`
})

var app = new Vue({
el: "#app",
data: {
pmsg: '我是父组件的信息',
parr: ['orange','apple','banana','watermelen'],
fontSize: 10
},
methods: {
handle: function() {
// 扩大字体大小
this.fontSize += 5;
}
}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_插槽_04

Vue 学习笔记 —— 组件化开发 (三)_插槽_05

2.3 子组件通过自定义事件向父组件传递信息

基本和上面一致

子组件传递的数据,在父组件中要通过 $event 来接收数据

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>子组件向父组件传递数据</title>
</head>
<body>

<div id="app">
<div :style="{fontSize: fontSize + 'px'}">{{pmsg}}</div>
<menu-item :parr="parr" @enlarge-text="handle($event)"></menu-item>
</div>

<script src="../vue.js"></script>
<script>
// 子组件自定义向父组件传值 —— 基本用法
/**
* props 传递数据原则,单向数据流
* 1. 子组件通过自定义事件向父组件传递信息 $emit
* 2. 父组件监听子组件的事件
* 3. 父组件通过 $event 获取值
* */
Vue.component('menu-item', {
props: ['parr'],
template:`
<div>
<ul>
<li :key="index" v-for="(item, index) of parr">{{item}}</li>
</ul>
<button @click="parr.push('lemon')">点击</button>
<button @click="$emit('enlarge-text',5)">扩大父组件中字体大小</button>
<button @click="$emit('enlarge-text',10)">扩大父组件中字体大小</button>
</div>
`
})

var app = new Vue({
el: "#app",
data: {
pmsg: '我是父组件的信息',
parr: ['orange','apple','banana','watermelen'],
fontSize: 10
},
methods: {
handle: function(val) {
// 扩大字体大小
this.fontSize += val;
}
}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_插槽_06

2.4 非父子组件间传值 (兄弟组件之间数据交互)

通过事件中心完成交互

Vue 学习笔记 —— 组件化开发 (三)_组件化_07

使用方式:


  1. 单独创建一个 Vue 实例
  2. 然后处理事件的监听 和 销毁

// 单独创建时间中心管理组件间的通信
var eventHub = new Vue();

// 监听事件和销毁事件
eventHub.$on('add-todo',addTodo); // 自定义事件名称 事件函数
eventHub.$off('add-tod');

// 触发事件
eventHub.$emit('add-todo',id);

示例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>组件化开发</title>
</head>
<body>
<div id="app">
<div>事件销毁</div>
<div>
<button @click="handle">点击</button>
</div>
<!-- 每个组件的都是相互独立的 -->
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>

<script src="../vue.js"></script>
<script>
/**
* 兄弟组件传值
* */
// 提供事件中心
var eventHub = new Vue();

Vue.component('test-tom', {
data() {
return {
num: 0
}
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
eventHub.$emit('jerry-event',2);
}
},
mounted() {
// 监听事件, 使用箭头函数,使用 this
eventHub.$on('tom-event', (val)=> {
this.num+=val;
})
}
})

Vue.component('test-jerry', {
data() {
return {
num: 0
}
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
eventHub.$emit('tom-event',1);
}
},
mounted() {
// 监听事件, 使用箭头函数,使用 this
eventHub.$on('jerry-event', (val)=> {
this.num+=val;
})
}
})


var app = new Vue({
el: "#app",
data: {

},
methods: {
// 事件销毁
handle: function() {
eventHub.$off('tom-event');
eventHub.$off('jerry-event');
}
}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_html_08

2.5 组件插槽


  • 父组件向子组件传递模板内容
  • 子组件通过插槽 slot 显示父组件中模板的数据

slot 是 vue 提供的 API,使用 slot 在子组件,我们可以在模板中插入我们想要的数据,我们还可以在 slot 中添加默认的数据

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>组件化开发</title>
</head>
<body>
<div id="app">
<test-box>
<h3>我没有通过 slot,我进不来</h3>
</test-box>
<hr>
<alert-box>
<h3>我通过 slot 插入进来了</h3>
</alert-box>
</div>

<script src="../vue.js"></script>
<script>
Vue.component('test-box',{
template: `
<div>
<strong>没插槽的时候</strong>
<div>
`,
})

Vue.component('alert-box', {
template: `
<div>
<strong>有插槽的时候</strong>
<slot></slot>
<div>
`,
})
var app = new Vue({
el: "#app",
data: {

}
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_html_09

2.6 具名插槽

在一个组件中,我们可以指定多个插槽插入数据,但是为了区分这些数据,我们会设置一个 name 值来标识唯一的插槽

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>组件化开发</title>
</head>
<body>
<div id="app">
<!-- slot 根据名称匹配
匹配的到的就会进入指定插槽
匹配不到的就会进入默认插槽
使用 template 可以包含多个标签,不使用它只能包含一个标签
-->
<base-layout>
<p slot="header">标题信息</p>
<p>我是主要内容</p>
<p>我是主要内容</p>
<p slot="footer">底部信息</p>
</base-layout>
<hr />

<base-layout>
<template slot="header">
<p>标题信息1</p>
<p>标题信息2</p>
</template>
<p>我是主要内容</p>
<p>我是主要内容</p>
<template slot="footer">
<p>底部信息1</p>
<p>底部信息2</p>
</template>
</base-layout>
</div>

<script src="../vue.js"></script>
<script>
Vue.component('base-layout', {
template: `
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`
})
var app = new Vue({
el: "#app"
})
</script>
</body>
</html>

Vue 学习笔记 —— 组件化开发 (三)_html_10

2.7 作用域插槽

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

使用方式:


  1. 在子组件中设置 slot,并自定义一个属性,接收父组件的内容
  2. 父组件创建 template,通过设置 slot-scope 就可以接收到子组件的内容
  3. 然后得到数据,就可以对数据进行显示了。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>作用域插槽</title>
</head>
<style>
.current {
color: orange;
}
</style>
<body>
<!-- 父组件对子组件的内容加工处理 -->
<div id="app">
<first-fruit :list="list">
<!-- 得到子组件通过 slot 传过来的数据, 并对数据加工处理 -->
<template slot-scope="slotProps">
<strong v-if="slotProps.info.id == 2" class="current">
{{slotProps.info.name}}
</strong>
<span v-else>
{{slotProps.info.name}}
</span>
</template>
</first-fruit>
</div>
<script src="../vue.js"></script>
<script type="text/javascript">
Vue.component('first-fruit',{
props: ['list'],
template: `
<div>
<ul>
<li v-for="item of list" :key="item.id">
<slot :info='item'>
{{item.name}}
</slot>
</li>
</ul>
</div>
`
})
var vm = new Vue({
el:"#app",
data: {
list: [{
id: 1,
name: 'apple'
},{
id: 2,
name: 'banana'
},{
id: 3,
name: 'orange'
}]
}
})
</script>
</body>
</html>



举报

相关推荐

0 条评论