vue实践二:页面区块化与组件封装

本文示例代码:查看源码    查看运行
参考书籍:《Vue2 实践揭秘》第四章:页面区块化与组件封装

本文代码从之前文章:vue-router:路由与页面间导航开始

一、文章目的

1、简单了解并学习vue页面区块化与组件的封装;
2、学习了解常用vue插件:

二、需求梳理

效果图1

效果图2

逻辑分析

  • 当前页面是Home.vue,我们在src/components新建home文件夹存放当前页专用组件;

布局分析

  • 热门推荐:Slider.vue
  • 快讯:Announcement.vue
  • 新书上架:BookList.vue
  • 编辑推荐:BookList.vue
  • 图书弹层:Dialog.vue

三、书写代码

  1. 搭架子
  • components下新建home文件夹,并新建四个vue组件;
  • Home.vue文件中引入组件,并在页面中占位;
    搭架子
  1. 热门推荐图片轮播实现:Swiper.vue
  • 2.1 安装依赖包


    安装swiper
  • 2.2 初始化 Swiper.vue
    • 这里图片使用图片占用官网 或者 这里
    • 使用ref属性定位,替换css选择器
    • 在js代码前加注释:// eslint-disable-next-line,阻止Do not use 'new' for side effects报错
<template>
  <div class="swiper-container" ref="slider">
    <div class="swiper-wrapper">
      <div class="swiper-slide"><img src="http://via.placeholder.com/300x120?text=1" alt=""></div>
      <div class="swiper-slide"><img src="http://via.placeholder.com/300x120?text=2" alt=""></div>
      <div class="swiper-slide"><img src="http://via.placeholder.com/300x120?text=3" alt=""></div>
    </div>
    <div class="swiper-pagination" ref="pagination"></div>
  </div>
</template>
<script>
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.css'
export default {
  props: ['slides'],
  mounted () {
    this.swiperInit()
  },
  methods: {
    swiperInit () {
      // eslint-disable-next-line
      new Swiper(this.$refs.slider, {
        pagination: {
          el: this.$refs.pagination,
          clickable: true
        },
        spaceBetween: 0,
        centeredSliders: true,
        autoplay: {
          delay: 2000
        },
        autoplayDisabledOninteraction: true,
        initialSlide: 0,
        loop: true,
        speed: 900
      })
    }
  }
}
</script>
  • 2.3 父组件Home.vue传递数据
    • 修改Home.vueSwiper.vue
    • 注意:通过接口获取数据时,组件引用加v-if判断,防止数据未加载完页面渲染造成bug
      数据传递
  • 2.4 实现效果


    效果
  1. 快讯实现:Announcement.vue
    快讯
  2. 新书上架和编辑推荐:BookList.vue
  • 4.1 初始化BookList.vue
<template>
  <div class="book-list">
    <div class="header">
      <div class="heading">最新更新</div>
      <div class="more">更多...</div>
    </div>
    <div class="book-item">
      <div class="book">
        <div class="cover"><img src="http://via.placeholder.com/100x150?text=1" alt=""></div>
        <div class="title">揭开数据真相:从小白到数据分析达人</div>
        <div class="author">Edward Zaccaro, Daniel Zaccaro</div>
      </div>
      <div class="book">
        <div class="cover"><img src="http://via.placeholder.com/100x150?text=1" alt=""></div>
        <div class="title">揭开数据真相:从小白到数据分析达人</div>
        <div class="author">Edward Zaccaro, Daniel Zaccaro</div>
      </div>
    </div>
  </div>
</template>
<script>
import './BookList.less'
export default {}
</script>

BookList.less

.book-list {
  margin: 0 14px;
  & > .header {
    display: table;
    width: 100%;
    border-bottom: 1px solid #efefef;

    & > .heading {
      display: table-cell;
      padding: 12px;
    }

    & > .more {
      display: table-cell;
      text-align: right;
      vertical-align: middle;
      font-size: 10px;
      color: #cccccc;
      padding-right: 14px;
    }
  }

  & .book-items {
    display: table;
    width: 100%;
    padding-top: 12px;
  }

  & .book {
    font-size: 10px;
    text-align: center;
    float: left;
    width: 33%;
    height: 207px;
    margin: 12px auto;
    cursor: pointer;
    & .cover {
    }

    & .title, & .authors {
      margin: 5px auto;
      width: 100px;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }

    & .authors {
      color: #898989;
      margin-top: 10px;
      text-align: left;
    }
  }
}
  • 4.2 父组件Home.vue传递数据

    • 更改Home.vueBookList.vue
    • 作者多个,加filters过滤器,用,拼接
      传递数据
  • 4.3 实现效果


    实现效果
  1. 弹出层:Dialog.vue
  • 5.1 Dialog.vue组件和Dialog.less
<template>
  <div class="dialog-wrapper" :class="{ 'open': is_open }">
    <div class="overlay" @click="close"></div>
    <div class="dialog">
      <!-- 头部及标题 -->
      <slot name="header"></slot>
      <!-- 内容区域 -->
      <slot></slot>
    </div>
  </div>
</template>
<script>
import './Dialog.less'
export default {
  data () {
    return {
      is_open: false
    }
  },
  methods: {
    open () {
      this.is_open = true
    },
    close () {
      if (this.is_open) {
        this.$emit('dialogClose')
      }
      this.is_open = false
    }
  }
}
</script>
.dialog-wrapper {
  &.open {
    display: block;
  }
  height: 100%;
  display: none;
  &>.overlay {
    background: rgba(0, 0, 0.3, 0.2);
    z-index: 1;
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
  }
  &>.dialog {
    z-index: 10;
    background: #fff;
    position: fixed;
    top: 24px;
    right: 24px;
    left: 24px;
    bottom: 24px;
    padding: 24px 14px;
    box-shadow: rgba(0, 0, 0, .8);
    & heading {
      padding: 12px;
    }
  }
}
  • 5.2 修改BookList.vue,添加点击事件@click="$emit('onBookSelect', book)"
    点击事件
  • 5.3 修改Home.vue,响应点击事件
    • book-list组件上添加@onBookSelect="preview($event)"响应BookList.vue的点击事件,并触发preview方法打开弹出层;
    • Dialog.vue@click="close"关闭弹层类似逻辑;
      Home.vue
  1. data数据改为接口获取
  • 6.1 安装vue-resource

    安装vue-resource

    • main.js中引入,并添加配置
      修改main.js
    • Home.vuecreated中通过vue-resource测试请求
      vue-resource
  • 6.2 安装axios

    image.png

    • main.js中引入
      修改main.js
    • Home.vuecreated中测试请求
      测试axios
  1. 没有正式的接口,下面通过mockjs拦截模拟接口请求
  • 7.1 安装mockjs
    image.png
  • 7.2 修改Home.vuedata
    image.png
  • 7.3 在src目录下新建api/home.json文件,加入json数据
{
  "slides": [
    { "id": 1, "img_url": "1.png" },
    { "id": 2, "img_url": "2.png" },
    { "id": 3, "img_url": "3.png" }
  ],
  "announcement": "今日上架的图书全部8折",
  "latestUpdated": [
    {
      "id": 1,
      "title": "揭开数据真相:从小白到数据分析达人",
      "authors": [ "Edward Zaccaro", "Daniel Zaccaro" ],
      "img_url": "http://via.placeholder.com/100x150?text=1"
    },
    {
      "id": 2,
      "title": "Android高级进阶",
      "authors": ["顾浩鑫"],
      "img_url": "http://via.placeholder.com/100x150?text=2"
    },
    {
      "id": 3,
      "title": "淘宝天猫电商运营与数据化选品完全手册",
      "authors": ["老夏"],
      "img_url": "http://via.placeholder.com/100x150?text=3"
    },
    {
      "id": 4,
      "title": "大数据架构详解:从数据获取到深度学习",
      "authors": ["朱洁", "罗华霖"],
      "img_url": "http://via.placeholder.com/100x150?text=4"
    },
    {
      "id": 5,
      "title": "Meteor全栈开发",
      "authors": ["杜亦舒"],
      "img_url": "http://via.placeholder.com/100x150?text=5"
    }
  ],
  "recommended": [
    {
      "id": 1,
      "title": "自己动手做大数据系统",
      "authors": ["张粤磊"],
      "img_url": "http://via.placeholder.com/100x150?text=1"
    },
    {
      "id": 2,
      "title": "智能硬件安全",
      "authors": ["刘建皓"],
      "img_url": "http://via.placeholder.com/100x150?text=2"
    },
    {
      "id": 3,
      "title": "实战数据库营销--大数据时代轻松赚钱之道(第2版)",
      "authors": ["罗安林"],
      "img_url": "http://via.placeholder.com/100x150?text=3"
    },
    {
      "id": 4,
      "title": "大数据思维--从掷骰子到纸牌屋",
      "authors": ["马继华"],
      "img_url": "http://via.placeholder.com/100x150?text=4"
    },
    {
      "id": 5,
      "title": "从零开始学数据营销",
      "authors": ["韩布韦"],
      "img_url": "http://via.placeholder.com/100x150?text=5"
    },
    {
      "id": 6,
      "title": "数据化营销",
      "authors": ["龚正", "吴治辉", "王伟", "崔秀龙", "闫建勇"],
      "img_url": "http://via.placeholder.com/100x150?text=6"
    }
  ]
}
  • 7.4 在src下新建mock.js,并在main.js中引入
    mock.js
import Mock from 'mockjs'
import HomePageData from '@/api/home.json'

let sliderImages = require.context('./assets/sliders', false, /\.(png|jpg|gif|svg)$/)
HomePageData.slides.forEach((slide) => {
  slide.img_url = sliderImages('./' + slide.img_url)
})

Mock.mock('/api/home', 'post', HomePageData)
Mock.mock('https://api.coindesk.com/v1/bpi/currentprice.json', 'get', HomePageData)
在main.js中添加mock.js
  • 7.5 在src/assets下新建slides文件夹,并加入三张图片
    slides图片
  • 7.6 通过mock拦截接口请求,给data数据重新赋值


    mock模拟接口
  • 7.7 实现效果


    效果图

结语:当前示例很简单,入门学习理清思路可以。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容