组件的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 3、使用组件,必须在Vue挂载实例中使用 -->
<!-- 全局组件可以在任意Vue挂载实例中使用 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script>
// 1、创建组件构造器对象
const cpnC = Vue.extend({
// 代表自定义组件模板
template: `
<div>
<h2>我是标题</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
`
});
// 2、注册组件(组件标签名, 组件构造器对象)
// 全局组件,意味着可以在多个Vue实例下面使用
Vue.component('my-cpn', cpnC);
const app = new Vue({ el: '#app' })
</script>
</body>
</html>
注册局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 3、使用组件,必须在Vue挂载实例中使用 -->
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app2">
<!-- 局部组件在其他Vue挂载中无法使用 -->
<cpn></cpn>
</div>
<script>
// 1、创建组件构造器对象
const cpnC = Vue.extend({
// 代表自定义组件模板
template: `
<div>
<h2>我是标题</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
`
});
const app = new Vue({
el: '#app',
// 局部组件
// 2、注册组件
components: {
cpn:cpnC
}
});
const app2 = new Vue({ el: '#app2' })
</script>
</body>
</html>
父组件与子组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 使用组件 -->
<cpn2></cpn2>
</div>
<script>
// 1、创建第一个组件构造器(子组件)
const cpnC1 = Vue.extend({
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容。。。。。。</p>
</div>
`
})
// 2、创建第二个组件构造器(父组件)
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容。。。。。。</p>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
})
// root组件
const app = new Vue({
el: '#app',
components: {
cpn2: cpnC2
}
})
</script>
</body>
</html>
注册组件语法糖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 使用组件 -->
<global-tag></global-tag>
<localtag></localtag>
</div>
<script>
// 组件语法糖
// 全局组件
Vue.component('global-tag', {
template: `
<div>
<h2>我是全局组件标题</h2>
<p>我是内容。。。。。。</p>
</div>
`
})
// root组件
const app = new Vue({
el: '#app',
components: {
// 局部组件语法糖
localtag: {
template: `
<div>
<h2>我是局部组件标题</h2>
<p>我是内容。。。。。。</p>
</div>
`
}
}
})
</script>
</body>
</html>
组件模板分离的写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 使用组件 -->
<global-tag></global-tag>
<localtag></localtag>
</div>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!-- 1.模板分离写法一: script标签,要注意类型 -->
<script type='text/x-template' id='cpn'>
<div>
<h2>我是全局组件标题</h2>
<p>我是内容。。。。。。</p>
</div>
</script>
<!-- 2.模板分离写法一: template标签 -->
<template id='cpn2'>
<div>
<h2>我是局部组件标题</h2>
<p>我是内容。。。。。。</p>
</div>
</template>
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<script>
// 组件语法糖
// 全局组件
Vue.component('global-tag', {
template: '#cpn'
})
// root组件
const app = new Vue({
el: '#app',
components: {
// 局部组件语法糖
localtag: {
template: '#cpn2'
}
}
})
</script>
</body>
</html>
组件中数据存放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- 使用组件 -->
<global-tag></global-tag>
<localtag></localtag>
</div>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!-- 组件模板分离 -->
<template id='cpn'>
<div>
<!-- 组件中数据存放 -->
<h2>{{title}}</h2>
<p>{{content}}</p>
</div>
</template>
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<script>
// 全局组件
Vue.component('global-tag', {
template: '#cpn',
data() {
return {
title: "我是全局组件标题。。。",
content: "我是全局组件的内容。。。。。。"
}
}
})
// root组件
const app = new Vue({
el: '#app',
// 局部组件
components: {
// 组件名
localtag: {
// 绑定的模板
template: '#cpn',
// 组件数据
// data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存着数据
data() {
return {
title: '我是局部组件标题。。。',
content: "我是局部组件的内容。。。。。。"
}
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- -----------使用组件----------------- -->
<global-tag></global-tag>
<global-tag></global-tag>
<global-tag></global-tag>
</div>
<!-- ===================================== -->
<!-- -----------组件模板----------------- -->
<template id='cpn'>
<div>
<h2>当前计数:{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<!-- ======================================= -->
<script>
// 全局组件
Vue.component('global-tag', {
template: '#cpn',
data() {
return {
counter: 0
}
},
methods: {
increment(){
this.counter++
},
decrement(){
this.counter--
}
}
})
// root组件
const app = new Vue({ el: '#app' })
</script>
</body>
</html>
父子组件的通信
父传子props
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id='app'>
<!-- -----------使用组件----------------- -->
<soncpn :smessage="message" :smovies='movies'></soncpn>
</div>
<!-- ===================================== -->
<!-- --------------组件模板----------------- -->
<template id='son-temp'>
<div>
<h2>{{smessage}}</h2>
<p>{{smovies}}</p>
<ul>
<li v-for="item in smovies">{{item}}</li>
</ul>
</div>
</template>
<!-- ======================================= -->
<script>
// 父传子:props
const soncpn = {
template: '#son-temp',
// 数组写法
// props: ['smessage', 'smovies'],
// 对象写法:可以对数据进行类型限制
// props: {
// smessage: String,
// smovies: Array
// },
// 对象写法:可以对数据提供一些默认值
props: {
smessage: {
type: String,
default: 'aaaa',
// 表示必填的字符串
// required: true
},
smovies: {
// 类型是对象或者数组时,默认值必须是一个函数
type: Array,
default(){
return ['1', '2', '3']
}
}
}
}
// root组件
const app = new Vue({
el: '#app',
data: {
message: '电影清单',
movies: ['如果可以重来', '高中时代', '初中的懵懂'],
},
components: {
soncpn
},
})
</script>
</body>
</html>
子传父(自定义事件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<!-- 父组件监听发射过来的自定义事件 -->
<h2>计数器:{{count}}</h2>
<soncpn @increment="changeCount" @decrement='changeCount'></soncpn>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>
<button @click='add(count)'>+</button>
<button @click='sub(count)'>-</button>
</div>
</template>
<!-- ======================================= -->
<script>
// 子组件
const soncpn = {
template: '#son-temp',
data() {
return {
count: 0
}
},
methods: {
add(count){
// console.log(this.count++)
// 向父组件发射一个自定义事件
this.count++
this.$emit('increment', this.count)
},
sub(){
this.count--
this.$emit('decrement', this.count)
}
}
}
// 父组件
const app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
changeCount(count){
this.count = count
}
},
components: {
soncpn
},
})
</script>
</body>
</html>
父组件访问子组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<soncpn></soncpn>
<soncpn></soncpn>
<soncpn></soncpn>
<button @click='btnClick'>按钮</button>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>我是子组件</div>
</template>
<!-- ======================================= -->
<script>
// 父组件
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
methods: {
btnClick(){
// 1、$children:获取所有子组件
console.log(this.$children);
this.$children[0].showMessage();
console.log(this.$children[0].name)
}
},
// 子组件
components: {
soncpn : {
template: '#son-temp',
data() {
return {
name : 'kuse'
}
},
methods: {
showMessage(){
console.log("hi-------kuse")
}
}
}
},
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<soncpn ref='aaa'></soncpn>
<soncpn></soncpn>
<soncpn></soncpn>
<button @click='btnClick'>按钮</button>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>我是子组件</div>
</template>
<!-- ======================================= -->
<script>
// 父组件
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
methods: {
btnClick(){
// 2、$refs: (获得指定子组件)对象类型,默认是一个空的对象 ref = '对象名'
console.log(this.$refs);
console.log(this.$refs.aaa);
console.log(this.$refs.aaa.name);
this.$refs.aaa.showMessage();
}
},
// 子组件
components: {
soncpn : {
template: '#son-temp',
data() {
return {
name : 'kuse'
}
},
methods: {
showMessage(){
console.log("hi-------kuse")
}
}
}
},
})
</script>
</body>
</html>
插槽 slot
基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<soncpn></soncpn>
<soncpn>
<!-- 插槽放在子组件标签内 -->
<button>插槽</button>
</soncpn>
<soncpn>
<span style="color:red">我是通过插槽插进来的</span>
</soncpn>
<soncpn>
<!-- 子组件标签内有多个值时,都会替换 -->
<p style="color:red">我是通过插槽插进来的--</p>
<p style="color:red">我是通过插槽插进来的--</p>
<p style="color:red">我是通过插槽插进来的--</p>
</soncpn>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>
<h1>子组件</h1>
<div>我是子组件</div>
<slot>
<p>插槽的默认内容,当调用子组件没有添加插槽内容时,显示默认内容,如果自定义了插槽,则默认内容会被覆盖</p>
</slot>
</div>
</template>
<!-- ======================================= -->
<script>
// 父组件
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
// 子组件
components: {
soncpn : {
template: '#son-temp',
},
}
})
</script>
</body>
</html>
具名插槽
- 一个不带 name 的 < slot > 出口会带有隐含的名字“default”
- 在向具名插槽提供内容的时候,我们可以在一个 < template > 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称
- 现在 < template > 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 < template > 中的内容都会被视为默认插槽的内容
- 然而,如果你希望更明确一些,仍然可以在一个 < template > 中包裹默认插槽的内容
- 注意 v-slot 只能添加在 < template > 上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<soncpn>
<template v-slot:left>
<i>---左边---</i>
</template>
<template v-slot:default>
<h1>---标题---</h1>
</template>
<template v-slot:right>
<b>---右边---</b>
</template>
</soncpn>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>
<slot name='left'>
<p>左边</p>
</slot>
<slot>
<p>中间</p>
</slot>
<slot name='right'>
<p>右边</p>
</slot>
</div>
</template>
<!-- ======================================= -->
<script>
// 父组件
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
// 子组件
components: {
soncpn : {
template: '#son-temp',
},
}
})
</script>
</body>
</html>
插槽作用域
父组件替换插槽的标签,但是内容还是由子组件来提供
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vuejs</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<soncpn></soncpn>
<soncpn>
<!-- 定义一个引用作用域名,并指向所引用的插槽对象 -->
<template v-slot:default='slotProps'>
<!-- 通过上面定义的作用域名来访问插槽原来数据 -->
<span v-for='item in slotProps.data'>{{item}} ++ </span>
<hr>
<span>{{slotProps}}</span>
</template>
</soncpn>
</div>
<!-- ===================================== -->
<!-- 子组件模板 -->
<template id='son-temp'>
<div>
<!-- 为了codeLang在父级的插槽可用,我们将codeLang绑定到<slot>元素上 -->
<!-- 绑定在<slot> 元素上的属性称为插槽props-->
<!-- 这样我们在父级作用域中,我们就可以使用带值的v-slot来定义我们提供插槽props的名字 -->
<slot :data='codeLang'>
<ul>
<li v-for="item in codeLang">{{item}}</li>
</ul>
</slot>
</div>
</template>
<!-- ======================================= -->
<script>
// 父组件
const app = new Vue({
el: '#app',
// 子组件
components: {
soncpn : {
template: '#son-temp',
data(){
return {
codeLang : ['c', 'c++', 'java', 'python', 'js']
}
}
},
}
})
</script>
</body>
</html>