Vue组件化开发
- 组件化开发思想
- 组件祖册
- Vue调试工具用法
- 组件间数据交互
- 组件插槽
- 基于组件的案例
组件化的开发思想
编程中的组件化开发思想
一个组件就是一个功能,多个组件组成一个完整的APP,抽取一个组件并不会影响其它组件的运行。
组件化规范: Web Components
官网:https://developer.mozilla.org...
组件的注册
组件的注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue组件的使用</title>
</head>
<body>
<div id="app">
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
</div>
</body>
<script src="../vue.js"></script>
<script>
Vue.component('button-count', {
data() {
return {
count: '0',
}
},
template: `<button @click='count++'>点击{{count}}次</button>`
})
let vm = new Vue({
el: "#app",
data: {
}
})
</script>
</html>
Vue组件注册之注意事项
注意事项
- dta必须是一个函数
- 组件模板内容必须是单个根元素
- 组件模板内容可以是模板字符串(ES6语法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue组件的注意事项</title>
</head>
<body>
<div id="app">
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
</div>
</body>
<script src="../vue.js"></script>
<script>
Vue.component('button-count', {
//data必须是一个函数
data() {
return {
count: '0',
}
},
//组件模板的内容必须是单个根元素 且可以使用模板字符串语法
template: `
<div>
<button @click='count++'>点击{{count}}次</button>
<button>按钮</button>
</div>
`
})
let vm = new Vue({
el: "#app",
data: {
}
})
</script>
</html>
组件的命名方式
注意事项
- 驼峰方式的命名能在组件注册的字符串模板中使用,但不能在标签中的模板字符串使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue组件的命名</title>
</head>
<body>
<div id="app">
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
<myComponent></myComponent>
</div>
</body>
<script src="../vue.js"></script>
<script>
Vue.component('myComponent', {
data() {
return {
msg: 'hello Word'
}
},
template: `<div>{{msg}}</div>`
})
Vue.component('button-count', {
//data必须是一个函数
data() {
return {
count: '0',
}
},
// 采用驼峰式命名的方式可以在组件定义中的模板字符串使用
template: `
<div>
<button @click='count++'>点击{{count}}次</button>
<button>按钮</button>
<myComponent></myComponent>
</div>
`
})
let vm = new Vue({
el: "#app",
data: {
}
})
</script>
</html>
Vue之局部自定义组件
使用components属性可以局部自定义组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<hello-word></hello-word>
<hello-vue></hello-Vue>
</div>
</body>
<script src='../vue.js'></script>
<script>
let helloWord = {
data() {
return {
msg: 'hello Word'
}
},
template: `<div>{{msg}}</div>`
};
let helloVue = {
data() {
return {
msg: 'hello Vue'
}
},
template: `<div>{{msg}}</div>`
};
let vm = new Vue({
el: "#app",
data() {
return {
}
},
// 局部自定义组件
components: {
'hello-word': helloWord,
'hello-vue': helloVue
}
})
</script>
</html>
Vue之调试工具的使用
组件间数据交互
子组件向父组件传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{value}}</div>
<menu-item v-bind:title='title' v-bind:value='value'></menu-item>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 子组件向父组件传值的基本使用
Vue.component('menu-item', {
props: ['title', 'value'],
data() {
return {
msg: "子组件本身的内容"
}
},
template: `<div>{{msg +'---'+title+'---'+value}}</div>`
})
let vm = new Vue({
el: "#app",
data() {
return {
value: "父组件的内容",
title: '动态绑定属性'
}
},
})
</script>
</html>
props属性名规则
- 在props中使用驼峰式命名,标签模板中需要使用短横线形式
- 字符串的模板并没有限制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>props的属性名规则</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<menu-item :menu-item='title'></menu-item>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 父组件向子组件传值 props的属性名规则
Vue.component('menu-item', {
props: ['menuItem'],
template: `<div>{{menuItem}}</div>`
})
var vm = new Vue({
el: "#app",
data() {
return {
msg: 'hello word',
title: 'props的命名规则'
}
},
})
</script>
</html>
props属性值类型
- 字符串String
- 数值 Number
- 布尔值 Boolean
- 数组 Array
- 对象 Object
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue之props属性值的类型</title>
</head>
<body>
<div id="app">
<menu-item :string='string' :number='number' :boolean='boolean' :arr='arr' :obj='obj'></menu-item>
</div>
</body>
<script src='../vue.js'></script>
<script>
Vue.component('menu-item', {
props: ['number', 'string', 'boolean', 'arr', 'obj'],
template: `<div>
<div>{{string}}</div>
<div>{{number}}</div>
<div>{{boolean}}</div>
<ul>
<li :key='item.id' v-for='(item,index) in arr'>{{item}}</li>
</ul>
<div>{{obj.name}}</div>
</div>`
});
let vm = new Vue({
el: "#app",
data() {
return {
string: 'hello Vue',
number: '2',
boolean: true,
arr: ['apple', 'learn', 'lick'],
obj: {
name: '尧子陌',
age: 18
}
}
},
})
</script>
</html>
子组件向父组件传值
props传递数据原则:单向数据流
子组件通过自定义事件向父组件传值
父组件监听子组件的事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子组件向父组件传递值</title>
</head>
<body>
<div id="app">
<div :style="{fontSize:fontSize+'px'}">
{{msg}}
</div>
<menu-item @large-text='handle'></menu-item>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 定义子组件
Vue.component('menu-item', {
template: `
<div>
<button @click='$emit("large-text")'> 扩大父组件的字体</button>
</div>`
})
let vm = new Vue({
el: '#app ',
data() {
return {
msg: '父组件的container ',
fontSize: 10,
}
},
methods: {
handle: function() {
this.fontSize += 10;
}
},
})
</script>
</html>
子组件向父组件传递值且传递参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子组件向父组件传递值</title>
</head>
<body>
<div id="app">
<div :style="{fontSize:fontSize+'px'}">
{{msg}}
</div>
<menu-item @large-text='handle($event)'></menu-item>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 定义子组件
Vue.component('menu-item', {
template: `
<div>
<button @click='$emit("large-text",5)'> 扩大父组件的字体</button>
<button @click='$emit("large-text",20)'> 扩大父组件的字体</button>
</div>`
})
let vm = new Vue({
el: '#app ',
data() {
return {
msg: '父组件的container ',
fontSize: 10,
}
},
methods: {
handle: function(val) {
this.fontSize += val;
}
},
})
</script>
</html>
非父子组件间传值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<button @click='handle'></button>
<item-tom></item-tom>
<item-juy></item-juy>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 提供事件中心
let hub = new Vue()
// 创建子组件
Vue.component('item-tom', {
data() {
return {
num: 0,
}
},
template: `
<div>
<div>{{num}}</div>
<button @click='handle'>按钮</button>
</dv>
`,
// 触发兄弟组件的事件
methods: {
handle: function() {
hub.$emit('juy-event', 2)
}
},
mounted() {
// 监听事件
hub.$on('tom-event', (val) => {
this.num += val;
})
},
})
// 创建子组件
Vue.component('item-juy', {
data() {
return {
num: 0,
}
},
template: `
<div>
<div>{{num}}</div>
<button @click='handle'>按钮</button>
</dv>
`,
methods: {
// 触发兄弟组件的事件
handle: function() {
hub.$emit('tom-event', 2)
}
},
mounted() {
// 监听事件
hub.$on('juy-event', (val) => {
this.num += val;
})
},
})
let vm = new Vue({
el: "#app",
data() {
return {
msg: '父组件',
}
},
methods: {
handle: function() {
hub.$off('tom-event');
hub.$off('juy-event')
}
},
})
</script>
</html>
组件插槽
插槽的基本用法
如果子组件没有使用插槽,父组件如果需要往子组件内容, 是没法做到的
插槽内容
插槽位置
注意事项
- 若slot里面有默认内容,则显示默认内容,若没有文字,则显示父组件模板中的slot的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<alert-box>container</alert-box>
<alert-box></alert-box>
</div>
</body>
<script src="../vue.js"></script>
<script>
//创建子组件
Vue.component('alert-box', {
template: `
<div>
<strong>Error</strong>
<slot>hello word</slot>
</div>
`
})
let vm = new Vue({
el: '#app',
data: {
}
})
</script>
</html>
具名插槽
具名卡槽的用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<base-lay>
<p slot='header'>header</p>
<p>main</p>
<p>main</p>
<p slot='footer'>footer</p>
</base-lay>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 定义子组件
Vue.component('base-lay', {
template: `<div>
<header>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='footer'></slot>
</footer>
</div>
`
})
let vm = new Vue({
el: '#app',
data() {
return {
}
},
})
</script>
</html>
作用域插槽
应用场景:父组件对子组件内容进行加工处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue作用域插槽</title>
<style>
.current {
background-color: purple;
}
</style>
</head>
<body>
<div id="app">
<fruit-list v-bind:list='list'>
<template slot-scope="slotProps">
<span v-if='slotProps.info.id==3' class="current">{{slotProps.info.name}}</span>
<span v-else>{{slotProps.info.name}}</span>
</template>
</fruit-list>
</div>
</body>
<script src="../vue.js"></script>
<script>
// 定义子组件
Vue.component('fruit-list', {
props: ['list'],
template: `<div>
<ul>
<li :key='item.id' v-for='(item,index) in list'>
<slot :info='item' >{{item.name}}</slot>
</li>
</ul>
</div>
`
})
let vm = new Vue({
el: '#app',
data() {
return {
list: [{
id: 1,
name: 'apple'
}, {
id: 2,
name: 'orange'
}, {
id: 3,
name: 'banner'
}, ]
}
},
})
</script>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。