自学Vue seven day!!!

弹框案例:

要求:

将弹窗内的内容在页面中展示;

点击按钮将弹窗关闭;

<!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、京东导航栏案例

image-20210612151106066.png

先预设好所有的插槽,然后在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">&lt;</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">&lt;</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> -->
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享