弹框案例:
要求:
将弹窗内的内容在页面中展示;
点击按钮将弹窗关闭;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html,body, #app1{
width: 100%;
height: 100%;
}
.wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: rgba(0,0,0, 0.3);
position: fixed;
top:0;
left: 0;
}
.content {
width: 220px;
height: 160px;
background-color: #fff;
}
.title {
height: 40px;
line-height: 40px;
text-align: center;
}
.msg {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 5px 10px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
height: 80px;
text-align: center;
color: gray;
font-size: 14px;
}
.bottom {
display: flex;
height: 40px;
line-height: 40px;
text-align: center;
}
.bottom div {
flex: 1;
color: green;
}
.bottom div:nth-of-type(1) {
border-right: 1px solid #eee;
color: red;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app1">
<p>点击结果:{{clickResult}}</p>
<div class="wrapper">
<div class="content">
<p class="title">bug提示</p>
<div class="msg">亲,你还有53633个bug,是否要处理?</div>
<div class="bottom">
<div>忽略,下班</div>
<div>加班处理</div>
</div>
</div>
</div>
</div>
</body>
<script>
// 现有以上布局,把wrapper抽取成子组件,通过传值的方式往内部传递数据
new Vue({
el: '#app1',
data: {
textObj: {
title: 'bug提示',
msg: '亲,你还有53633个bug,是否要处理?',
cancelTxt: '忽略,下班',
submitTxt: '加班处理'
},
clickResult:""
},
})
</script>
</html>
复制代码
完成之后的代码:
整体思路:
1、将整个弹窗编辑为一个组件;
2、在页面中使用组件,并将父级的textObj的对象传入组件中接收;
3、设置点击效果,将盒子wrapper设置一个v-show的参数来控制弹窗的显现;
4、在父组件定义一个需要修改内容的函数,并将此函数自定义在子组件中,在子组件调用;
5、将所需要的textObj.cancelTxt、textObj.submitTxt两个参数,通过子组件传入父组件进行修改,完成整个流程即可;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body,
#app1 {
width: 100%;
height: 100%;
}
.wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
left: 0;
}
.content {
width: 220px;
height: 160px;
background-color: #fff;
}
.title {
height: 40px;
line-height: 40px;
text-align: center;
}
.msg {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 5px 10px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
height: 80px;
text-align: center;
color: gray;
font-size: 14px;
}
.bottom {
display: flex;
height: 40px;
line-height: 40px;
text-align: center;
}
.bottom div {
flex: 1;
color: green;
}
.bottom div:nth-of-type(1) {
border-right: 1px solid #eee;
color: red;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app1">
<p>点击结果:{{clickResult}}</p>
<wrapper :text-obj='textObj' @fn='changeResult'></wrapper>
</div>
</body>
<template id="tmp">
<div class="wrapper" v-show='isShow'>
<div class="content">
<p class="title">{{textObj.title}}</p>
<div class="msg">{{textObj.msg}}</div>
<div class="bottom">
<div @click='handleClick(textObj.cancelTxt)'>{{textObj.cancelTxt}}</div>
<div @click='handleClick(textObj.submitTxt)'>{{textObj.submitTxt}}</div>
</div>
</div>
</div>
</template>
<script>
let wrapper = {
template: '#tmp',
data() {
return {
isShow: true
}
},
props: ["textObj"],
methods: {
handleClick(val) {
this.isShow = false;
this.$emit('fn', val)
}
}
}
// 现有以上布局,把wrapper抽取成子组件,通过传值的方式往内部传递数据
new Vue({
el: '#app1',
data: {
textObj: {
title: 'bug提示',
msg: '亲,你还有53633个bug,是否要处理?',
cancelTxt: '忽略,下班',
submitTxt: '加班处理'
},
clickResult: ""
},
components: {
wrapper
},
methods: {
changeResult(val) {
this.clickResult = val
}
},
})
</script>
</html>
复制代码
1、兄弟组件传参
使用中央事件总线 用法总结:
1、建立一个空的Vue对象;
2、在被修改的的组件中,定义mounted函数,在函数中通过bus发起自定义事件监听;
3、在需要修改值的地方,触发这个自定义事件,bus.$emit(“事件名”,参数1,参数2.。。);
<div id='app'>
<button1></button1>
<button2></button2>
</div>
<template id="tpm1">
<div>
<button :style="{backgroundColor: bgc}">按钮1</button>
</div>
</template>
<template id="tpm2">
<div>
<button @click='add()'>按钮2</button>
</div>
</template>
<script>
// 中央事件总线 用法总结:
// 1、建立一个空的Vue对象
// 2、在被修改的的组件中,定义mounted函数,在函数中通过bus发起自定义事件监听
// 3、在需要修改值的地方,触发这个自定义事件,bus.$emit(“事件名”,参数1,参数2.。。)
// 1、建立一个空的Vue对象
let bus = new Vue()
let button1 = {
template: '#tpm1',
data() {
return {
bgc: 'green'
}
},
mounted() {
// 2、在被修改的的组件中,定义mounted函数,在函数中通过bus发起自定义事件监听
bus.$on("changeBgcEvent", (val) => {
this.bgc = val
})
},
}
let button2 = {
template: '#tpm2',
data() {
return {
newColor: 'pink'
}
},
methods: {
add() {
// 3、在需要修改值的地方,触发这个自定义事件,bus.$emit(“事件名”,参数1,参数2.。。)
bus.$emit("changeBgcEvent", this.newColor)
}
},
}
new Vue({
el: '#app',
data: {
},
components: {
button1,
button2
}
})
</script>
复制代码
2、插槽
2.1、匿名插槽
1、组件标签内部手写HTML标签的时候,默认不做渲染;
2、需要把这些HTML标签展示在组件内部,需要用slot标签来接收;
3、slot便签出现的位置,就是将来这些HTML标签所在的位置,这种slot标签就成为插槽;
4、插槽加上name属性,称为具名插槽,反之称为匿名插槽;
<div id='app'>
<comp>
<a href="">a标签</a>
<button>按钮</button>
</comp>
</div>
<template id="tmp">
<div>
<slot></slot>
<p>p标签</p>
</div>
</template>
<script>
let comp = {
template: '#tmp'
}
new Vue({
el: '#app',
data: {
},
components: {
comp
}
})
</script>
复制代码
2.2、具名插槽
具名插槽需要name属性,值要和需要放在这里的标签的slot属性一致
<div id='app'>
<comp>
<a href="" slot="link">a标签</a>
<button slot="btn">按钮</button>
</comp>
</div>
<template id="tmp">
<div>
<slot name='link'></slot>
<p>p标签</p>
<slot name='btn'></slot>
</div>
</template>
<script>
let comp = {
template: '#tmp'
}
new Vue({
el: '#app',
data: {
},
components: {
comp
}
})
</script>
复制代码
2.3、京东导航栏案例
先预设好所有的插槽,然后在slot的位置切换名字,就可以切换相对应的内容
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.dh {
margin: 100px auto;
width: 400px;
height: 50px;
line-height: 50px;
text-align: center;
display: flex;
border: 1px solid #000;
}
.l,
.r {
width: 50px;
font-size: 30px;
}
.r {
line-height: 30px;
}
.c {
flex: 1;
}
ul {
display: flex;
justify-content: space-around;
}
</style>
</head>
<body>
<div id='app'>
<daoh>
<input type="text" slot="inp">
<h3 slot="h3">购物车</h3>
<ul slot="ul">
<li>商品</li>
<li>评价</li>
<li>详情</li>
</ul>
</daoh>
</div>
<template id="tmp">
<div class="dh">
<div class="l"><</div>
<div class="c">
<!-- 切换slot的名字,就可以切换相对应的内容 -->
<slot name='ul'></slot>
</div>
<div class="r">...</div>
</div>
</template>
<script>
let daoh = {
template: '#tmp'
}
new Vue({
el: '#app',
data: {
},
components: {
daoh
}
})
</script>
复制代码
2.4、导航栏功能切换
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.all {
margin: 100px auto;
}
.dh {
width: 400px;
height: 50px;
line-height: 50px;
text-align: center;
display: flex;
border: 1px solid #000;
}
.l,
.r {
width: 50px;
font-size: 30px;
}
.r {
line-height: 30px;
}
.c {
flex: 1;
}
ul {
display: flex;
justify-content: space-around;
}
</style>
</head>
<body>
<div id='app'>
<daoh>
<input type="text" slot="inp">
<h3 slot="h3">购物车</h3>
<ul slot="ul">
<li>商品</li>
<li>评价</li>
<li>详情</li>
</ul>
</daoh>
</div>
<template id="tmp">
<div class="all">
<div class="dh">
<div class="l"><</div>
<div class="c">
<!-- 切换slot的名字,就可以切换相对应的内容 -->
<slot :name='thisName'></slot>
</div>
<div class="r">...</div>
</div>
<button @click='add("inp")'>搜索</button>
<button @click='add("h3")'>购物</button>
<button @click='add("ul")'>详情</button>
</div>
</template>
<script>
let daoh = {
template: '#tmp',
data() {
return {
thisName: 'ul'
}
},
methods: {
add(val) {
this.thisName = val
}
},
}
new Vue({
el: '#app',
data: {
},
components: {
daoh
}
})
</script>
复制代码
2.5、作用域插槽
组件标签comp内部想要去使用组件中data数据时,不能直接使用,原因是不在作用域范围内。
解决办法:
1、把组件中的data中的数据传给对应的slot便签的标签属性 :mynum=’num’;
2、在slot所对应的标签上添加slot-scope属性,值是一个对象(名字自定义),这个对象接收了他所对应的slot标签的标签属性;
3、在这个标签上使用插值语法{{obj.mynum}} 就可以使用到子组件中的data数据;
<div id='app'>
<comp>
<button slot="btn" slot-scope='obj'>按钮{{obj.mynum}}、{{obj.tit}}</button>
</comp>
</div>
<template id="tmp">
<div>
<p>p标签</p>
<slot name='btn' :mynum='num' tit='ssss'></slot>
</div>
</template>
<script>
let comp = {
template: '#tmp',
data() {
return {
num: 20
}
}
}
new Vue({
el: '#app',
data: {
},
components: {
comp
}
})
</script>
复制代码
2.6、作用域插槽的多种写法
<!--
1、基本写法
<comp>
<button slot="btn" slot-scope='obj'>按钮{{obj.mynum}}、{{obj.tit}}</button>
</comp> -->
<!-- 2、基本写法之模板写法 -->
<comp>
<template slot="btn" slot-scope='obj'>
<button>按钮{{obj.mynum}}、{{obj.tit}}</button>
</template>
</comp>
<!--
3、指令写法
<comp v-slot:btn="obj">
<button>按钮{{obj.mynum}}、{{obj.tit}}</button>
</comp> -->
<!--
4、指令写法之模板写法
<comp>
<template v-slot:btn="obj">
<button>按钮{{obj.mynum}}、{{obj.tit}}</button>
</template> -->
复制代码