子传父:自定义事件 v-on
-
props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。我们应该如何处理呢?这个时候,我们需要使用自定义事件向父组件传递参数来完成。
-
我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。
自定义事件流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件。
举例:click事件
子组件:模板template中,建立一个click事件,@click="post(text),将要传递的数据作为参数。
子组件:建立post方法,用this.$emit(),发射自定义指令名和发射的参数
post(arg) { this.$emit('post-text', arg) }
在父!组件的模板HTML中,子组件标签上,添加自定义指令及方法
注意@post-text=“recData” recData 不要加参数或()
<message-cpn @post-text="recData"> </message-cpn>
在父组件中,写recData方法,来接收数据
methods: { recData(text) { console.log(text); } },
传递字符串
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/v2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<msg @post-text="rec"></msg>
</div>
<template id="msgTemplate">
<div>
<button @click="post(text)">{{text}}</button>
</div>
</template>
<script>
let msg = {
data() {
return {
text: '五一节日快乐!'
}
},
methods: {
post(text) {
// $emit 用于子组件向父组件传递数据的方法。
// 两个参数: 1、向父组件提供的一个自定义指令名。 2、子组件要发送出去的数据。
this.$emit('post-text', text)
}
},
template: msgTemplate
}
let app = new Vue({
el: '#app',
components: {
msg
},
methods: {
rec(value) {
alert(value)
}
},
})
</script>
</body>
</html>
传递对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/v2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<nav-list @item-click="goUrl"></nav-list>
</div>
<template id="navListTemplate">
<div>
<button v-for="(item,index) in navList" @click="post(item)" >{{item.name}}</button>
</div>
</template>
<script>
let navList = {
data() {
return {
navList: [
{id:1,name:"java"},
{id:2,name:"html"},
{id:3,name:"css"},
{id:4,name:"js"}
]
}
},
methods: {
post(item){
this.$emit('item-click',item)
}
},
template: navListTemplate
}
let app = new Vue({
el: '#app',
components: {
"nav-list":navList
},
methods: {
goUrl(item){
console.log(item);
}
},
})
</script>
</body>
</html>
兄弟组件通信
留坑,将工程的时候讲
访问组件DOM
- $parent 在子组件中访问父级DOM 不常用
- $children 在父组件访问子级DOM 1个子组件 肯定[0] 如果多个子组件 [0,1,2] 他的顺序是不一定的。需要数组进行一个遍历,才能应用
- $root 访问根DOM
- $refs 直接定位需要访问的组件
插槽
Vue 实现了一套内容分发的 API,将
<slot>
元素作为承载分发内容的出口,这是vue文档上的说明。具体来说,slot就是可以让你在组件内添加内容的‘空间’.使用插槽是在存在父子关系的组件,可以在子组件中决定插槽的位置,同时子组件也可以给这些插槽的默认信息,当父组件中没有需要给子组件插槽插入信息时,显示的是子组件插槽定义的默认信息。默认插槽: 通过父标签的内容 替换插槽内容
具名插槽 :给插槽命一个名。 通过父标签的内容 替换插槽内容
作用域插槽: 通过子组件的数据 在父组件里展示
默认插槽的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/v2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<top-cpn>时尚男鞋</top-cpn>
</div>
<!-- 插槽slot 是用在子组件的模板中 <slot></slot> -->
<template id="topTemplate">
<div>
<img src="img/btnstart.png" alt="" srcset="">
<span style="color: aquamarine;font-size: 30px;">
<slot></slot>
</span>
</div>
</template>
<script>
let topCpn = {
template: topTemplate,
}
let app = new Vue({
el: '#app',
components: {
"top-cpn":topCpn
}
})
</script>
</body>
</html>
具名插槽的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/v2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<top-cpn>
<template #one>
时尚男鞋
</template>
<template v-slot:three>
时尚女鞋
</template>
</top-cpn>
</div>
<!-- 插槽slot 是用在子组件的模板中 <slot></slot> -->
<template id="topTemplate">
<div>
<div class="testSolt">
<p class="title">具名插槽</p>
<!-- 给插槽加name 属性,就是所谓的具名插槽 -->
<slot name="one"></slot>
<slot name="two"></slot>
</div>
<!-- 子组件也可以同时定义多个具名插槽 -->
<div style="margin-top:300px;background:#fff;height:100px;color:blue;">
<slot name="three"></slot>
</div>
</div>
</template>
<script>
let topCpn = {
template: topTemplate,
}
let app = new Vue({
el: '#app',
components: {
"top-cpn": topCpn
}
})
</script>
</body>
</html>
作用域插槽的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/v2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<top-cpn >
<!-- 插槽里面同时可以插入一个组件 或者字符串内容等都可以 -->
<template v-slot="slotProps">
<p>{{slotProps.obj.msg}}---{{slotProps.obj.message}}</p>
</template>
</top-cpn>
</div>
<template id="topTemplate">
<div>
<div class="testSolt">
<p class="title">作用域插槽</p>
<!-- 子组件中告诉父组件,要实现obj里的信息 -->
<slot :obj="obj">默认信息</slot>
</div>
</div>
</template>
<script>
let topCpn = {
data() {
return {
obj: {
msg: '我是msg',
messge: '我是message'
}
}
},
template: topTemplate,
}
let app = new Vue({
el: '#app',
components: {
"top-cpn": topCpn
}
})
</script>
</body>
</html>
api
nextTick
set delete
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!-- <script src="https://unpkg.com/vue@next"></script> -->
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 插值表达式:通过两个大括号,把变量包起来 -->
<!-- <div ref="showtext">{{showText}}</div>-->
<button @click="addAge">添加年龄</button>
{{obj}}
</div>
<script>
let vm = new Vue({
el: '#app', // el = element的缩写 挂载到那个元素上,或者将来渲染到那个区域 id #app css基础选择器 # id . class
data: {
showText: 'Hello Vue',
obj: {
name: "hahaha",
sex: "男性"
}
},
mounted() {
// console.log(this.$refs.showtext.innerText);
},
methods: {
addAge() {
// this.obj.age = 12
// 动态添加对象的属性,并且希望在视图中实时更新
this.$set(this.obj,"age",18)
console.log(this.obj);
}
},
});
</script>
</body>
</html>