vue如何创建弹窗组件| 青训营笔记

180 阅读1分钟

这是我参与「第四届青训营 」笔记创作活动的第8天. vue如何创建弹窗组件 并增加背景蒙版.png

背景:


在同一个父组件中有两个子组件,其中一个子组件作为弹窗被隐藏,而另一个子组件中的按钮能够触发该弹窗子组件.

弹窗子组件:

html部分:

<template>
    <!-- 收藏列表 -->
    <div class="CollectList">
        <div class="title">
            <h1>选择收藏集</h1>
            <div class="sub_title">选择或创建你想添加的收藏集</div>
        </div>
    </div>
</template>

js部分:

<script>
export default {
    name: "CollectList",
}
</script>

css部分:

<style>
.CollectList {
    width: 520px;
    height: 486px;
    background: red;
}
</style>

触发弹窗组件的子组件

html部分:

<template>
  <!-- 详情页左侧 -->
  <div class="DetailPageLeft">
    <div class="DetailPageLeft_container">
      <!-- 点赞按钮 -->
      <div class="good">
        <div @mouseenter="good_enter" @mouseleave="good_leave" @click="good_num_click" class="img_container"
          :data_good_num="good_num_this">
          <img v-if="good_flag" src="../../assets/DetailPageLeft/good.png">
          <img v-if="!good_flag" src="../../assets/DetailPageLeft/good_active.png">
        </div>
      </div>
      <!-- 评论按钮 -->
      <div class="suggest">
        <div class="img_container" @mouseenter="suggest_enter" @mouseleave="suggest_leave"
          :data_suggest_num="suggest_num">
          <img v-if="suggest_flag" src="../../assets/DetailPageLeft/suggest.png">
          <img v-if="!suggest_flag" src="../../assets/DetailPageLeft/suggest_active.png">
        </div>
      </div>
      <!-- 收藏按钮 -->
      <div class="collect">
        <div class="img_container" @click="collect_click" @mouseenter="collect_enter" @mouseleave="collect_leave">
          <img v-if="collect_flag" src="../../assets/DetailPageLeft/collect.png">
          <img v-if="!collect_flag" src="../../assets/DetailPageLeft/collect_active.png">
        </div>
      </div>
      <!-- 分享按钮 -->
      <div class="share">
        <div class="img_container" @mouseenter="share_enter" @mouseleave="share_leave">
          <img v-if="share_flag" src="../../assets/DetailPageLeft/share.png">
          <img v-if="!share_flag" src="../../assets/DetailPageLeft/share_active.png">

        </div>
      </div>
      <!-- 举报按钮 -->
      <div class="report">
        <div class="img_container" @mouseenter="report_enter" @mouseleave="report_leave">
          <img v-if="report_flag" src="../../assets/DetailPageLeft/report.png">
          <img v-if="!report_flag" src="../../assets/DetailPageLeft/report_active.png">
        </div>
      </div>
      <!-- 阅读模式按钮 -->
      <div class="book">
        <div class="img_container" @mouseenter="book_enter" @mouseleave="book_leave">
          <img v-if="book_flag" src="../../assets/DetailPageLeft/book.png">
          <img v-if="!book_flag" src="../../assets/DetailPageLeft/book_active.png">
        </div>
      </div>
    </div>

  </div>
</template>

其中触发蒙版及弹唱的部分是收藏按钮部分.

js部分:

<script>
export default {
  name: "DetailPageLeft",
  data() {
    return {
      // flag_list: [true, true, true, true, true, true,],
      //判断光标是否进入各个图片按钮.
      good_flag: true,
      suggest_flag: true,
      collect_flag: true,
      share_flag: true,
      report_flag: true,
      book_flag: true,
      good_num_this: this.good_num,
      good_num_flag_this: this.good_flag,
    }
  },
  //接收点赞次数和留言数量.
  props: {
    good_num: {
      type: Number,  //类型判断
      required: true, //必要性
    },
    suggest_num: {
      type: Number,
      required: true,
    },
    //之前是否为本文章点赞.
    good_num_flag: {
      type: Boolean,  //类型判断
      required: true, //必要性
    }
  },

  methods: {
    //光标按钮进入事件,用于改变图片.
    good_enter() {
      this.good_flag = false;
    },
    good_leave() {
      this.good_flag = true;
    },
    suggest_enter() {
      this.suggest_flag = false;
    },
    suggest_leave() {
      this.suggest_flag = true;
    },
    collect_enter() {
      this.collect_flag = false;
    },
    collect_leave() {
      this.collect_flag = true;
    },
    share_enter() {
      this.share_flag = false;
    },
    share_leave() {
      this.share_flag = true;
    },
    report_enter() {
      this.report_flag = false;
    },
    report_leave() {
      this.report_flag = true;
    },
    book_enter() {
      this.book_flag = false;
    },
    book_leave() {
      this.book_flag = true;
    },
    //点击事件
    //点赞事件
    good_num_click() {
      if (!this.good_num_flag_this) {//还未点过赞.
        this.good_num_this++;
        this.good_num_flag_this = !this.good_num_flag_this;
      } else {
        this.good_num_this--;
        this.good_num_flag_this = !this.good_num_flag_this;
      }
    },
    //点击评论按钮.
    suggest_click() {//可尝试用组件通信,利用a标签定位实现.

    },
    collect_click() {//点击该按钮,将原有页面增加蒙版,然后跳出收藏夹组件
      // height: 100px;
      // background-color: #fff;
      // filter: Alpha(Opacity=60);
      // opacity: 0.6;
      this.$emit('get_collect_open_flag', true)
    },
  },

}

</script>

其中collect_click()实现了父子组件之间的通信,该子组件通过$emit向父组件传递名为get_collect_open_flag的true信息.告诉父组件要开启蒙版,弹出弹窗子件.

css部分:


<style>
.DetailPageLeft {
  width: 70px;
  height: 700px;
  color: #000;
  /* background: red; */
  padding-left: 30px;
}

.img_container {
  background: white;
  width: 50px;
  height: 50px;
  border: 0;
  border-radius: 50%;
}

.DetailPageLeft_container {
  position: absolute;
  top: 200px;
}

.good,
.suggest,
.collect,
.share,
.report,
.book {
  margin-bottom: 20px;
  position: relative;
}

.DetailPageLeft_container img {
  margin-top: 12px;
  width: 25px;
  height: 25px;
}

/*::after伪类选择器,为点赞按钮和评论按钮右上角增加数据*/
.good .img_container::after {
  content: attr(data_good_num);
}

.suggest .img_container::after {
  content: attr(data_suggest_num);
}

.img_container::after {
  position: absolute;
  border-radius: 9px;
  background-color: #c2c8d1;
  line-height: 17px;
  left: 75%;
  padding: 0 4px;
  /*增加padding 让背景更宽阔*/
}
</style>

父组件:

html:

<template>
    <!-- 文章详情页 -->
    <div class="DetailPage" id="DetailPage">
        <DetailPageLeft :suggest_num="suggest_num" :good_num="good_num" :good_num_flag="good_num_flag"
            @get_collect_open_flag="collect_open_flag"></DetailPageLeft>
        <CollectList v-if="collect_open_flag_this" class="CollectList"></CollectList>
        <button @click="close_collect">关闭蒙版</button>

    </div>
</template>

其中用v-if="collect_open_flag_this"来控制弹窗组件是否渲染,用 @get_collect_open_flag="collect_open_flag"来接收子组件的信息,知道该开启弹窗了.并且触发js的collect_open_flag();

js部分:


<script>
import DetailPageLeft from './DetailPageLeft.vue';
import CollectList from './CollectList.vue';

export default {
    name: "DetailPage",
    components: { DetailPageLeft, CollectList },
    data() {
        return {
            suggest_num: 13,
            good_num: 2,
            good_num_flag: true,
            collect_open_flag_this: false,
        }
    },
    methods: {
        // 打开蒙版
        collect_open_flag() {
            console.log(this.collect_open_flag_this);
            // console.log(document.getElementsByClassName('DetailPage'));
            document.getElementById('DetailPage').classList.add('masking');
            this.collect_open_flag_this = !this.collect_open_flag_this;
            document.getElementById('CollectList').classList.remove('masking');

        },
        // 关闭蒙版同时关闭收藏列表
        close_collect() {
            document.getElementById('DetailPage').classList.remove('masking');
            this.collect_open_flag_this = !this.collect_open_flag_this;
        }
    },
}

</script>

collect_open_flag_this: false变量控制着弹窗是否出现.collect_open_flag()打开弹窗创建蒙版,close_collect()关闭弹窗消去蒙版.其中通过this.collect_open_flag_this = !this.collect_open_flag_this;来改变变量的值来了控制弹窗. 而通过document.getElementById('DetailPage').classList.add('masking');来为容器标签增加类型,再通过css达到蒙版效果.

css:

<style>
.DetailPage {
    background: #e4e6eb;
    width: 200px;
    position: relative;

}

/*蒙版统一样式*/
.masking {
    background-color: #fff;
    filter: Alpha(Opacity=60);
    opacity: 0.6;
}

/* 收藏列表 */
.CollectList {
    position: fixed;
    top: 200px;
    left: 450px;
}
</style>

通过该类名达到创建蒙版的效果.

.masking {
    background-color: #fff;
    filter: Alpha(Opacity=60);
    opacity: 0.6;
}

效果图:

image.png 点击收藏按钮后

image.png