国庆挖个坑用vue写个bilibili

好久不写CSS了,之前的项目到后面全都是写JS,趁着这假期写个哔哩哔哩的WEB端。

vue-bilibili

预览: http://bilibili.summerscar.com/

在github上能找到很多类似的DEMO啦,但还是想自己从头写一个,包括前端+后端

技术找 vue + koa2 + es6 + async + scss

因为暂时先写个单页,没用vuex

项目托管:https://github.com/summerscar/bilibli-vue

记录

第一天

打算是VUE+KOA2来完成前后端,今天先完成准备工作,首页header简单的布局

  • bilibili网站有很多的图标,但是这些图标都是来自于一张PNG图片上,引用的方式是使用行内元素固定宽高,background-image引用图片,设置background-position得到对应图标。

  • header的横幅是直接div的background-image引入,position设为center

  • 横幅上方有个高斯模糊的效果,实现方式是在横幅内添加固定高度div引入图片,css设为filter:blur(3px)得到模糊后的图片,在该层上方再叠加一层白色带透明的div盖在模糊的图片上即可实现。(注意:由于模糊的边缘是类似AE中蒙板羽化,所以是个渐变的效果,为了隐藏渐变可以把height稍增加,然后定位把那部分藏起来)

第二天

还是在写这个header…

  • 清除浮动:在父元素设置

    1
    2
    3
    4
    5
    6
    7
    8
    &:after{
    content: '.';
    clear: both;
    width: 0;
    height: 0;
    display: block;
    visibility: hidden;
    }
  • 鼠标的各种hover效果,使用js事件+vue的ref去设置css即可

  • 还有些类似tip的小弹窗,暂时不清楚小箭头怎么弄的,我这边直接把这小弹窗放到该元素的after伪元素中,设置改元素的 div:hoer:after{}来设置显示和消失
  • 有些图片直接用接口的链接访问不到,使用后台代理获取图片然后返回给前端(注意:request的encode设为null否则默认为utf8,同时返回时设置type = ‘image/png’)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const router = require('koa-router')()
    const request = require('request-promise');

    // 处理传来图片

    router.get(/^\/image\/dynamic(?:\/|$)/, async (ctx, next) => {
    console.log(imageUrl.imgPrefix + ctx.url.split('/').slice(3).join('/'))
    let image = await request({url: imageUrl.imgPrefix + ctx.url.split('/').slice(3).join('/'), encoding: null})
    ctx.type = 'image/png'
    ctx.body = image
    })
  • 在动态的菜单中有一个下划线跟随li运动的动画我参考了官方的自己尝试下了: li的after伪元素给个小点,ul后面给个1px高的div,定位到点上面,根据点击的index,设置left值以及设置好transition就能实现动画效果

  • opacity失效的问题:在设置渐入渐出动画时发现同时设置display为none会导致opacity动画失效,将display改为visibility属性即可
  • 伪元素可以使用attr获取元素内的属性值 如: content:attr(‘data-url’)

第三天

  • block中文本overflow显示省略号(block需定义宽度)

    1
    2
    3
    4
    5
    {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    }
  • header中的各种下拉弹窗可以封装为一个基础组件,里面的ul与btn可以通过slot插入,部分css可以预先在基础组件里写好

  • z-index属性只对有定位的元素起效(除static)!!!
  • 文字前图标的简单处理:使用padding-left,再设置backround-image至对应处
  • 轮播图处理为基础组件,props接收数据以及相关参数的设置,通过emit将事件数据传递给父组件(组件也可以定义扩展方法,让父组件调用如:调转至某一index的图片)

第四天

  • 一觉醒来,我的天B站不仅换了头图,连主题都变了,还有这种操作的???

    我猜是这个style属性变了,过几天再确认下!!
  • 今天比较顺利,越写越顺了,发现个问题blackground-color设为线性渐变只写start和end color时,这个属性会间接性的抽风失效,中间加个stop color就又好了,好奇怪
  • 今天的进度

第五天

  • 没错,一觉醒来头图又换回去了,果然是这个style搞的鬼,我昨天补救的代码也生效了,能自动切换颜色了,23333我tm太机智了
  • 现在问题来了,下面的每个类目看起来差不多,但实际上又根据不同类目有区别,暂时想的是用slot插入或者根据不同的传入数据显示不同的组件
  • background-clip: border-box|padding-box|content-box; 规定背景的绘制区域:
  • v-for与v-if一起使用时v-for的优先级更高,在v-for的外面包一层div写v-if防止渲染报错
  • overflow:hidden 在定位元素中,被定位元素的overflow是根据定位的父元素属性来的
  • 文字下方的小三角写法回顾一下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    .active {
    color: $hoverBlue;
    border-bottom: 1px solid $hoverBlue;
    &:after {
    content: ' ';
    width: 0;
    height: 0;
    position: absolute;
    left: 50%;
    bottom: 0;
    border-left: 3px solid transparent;
    border-right: 3px solid transparent;
    border-bottom: 3px solid $hoverBlue;
    transform: translateX(-50%);
    }
    }
  • 今天挺顺利,完成了三个类目

  • 仔细研究了下,一共有5中不同的视频展示小窗口,分别是顶部的排行,紧跟着下面的推广,直播窗口,中部的各大类视频窗口,最后的推荐窗口,每种都单独做了一个组件

第六天

  • 在父子数据通信上遇到了些问题

    • 当子组件的emit出多个数据时

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      this.$emit('custom', 3, 4);
      // 父组件中
      <child @custom='todo(arguments)'></child>

      methods: {
      todo () {
      console.log(arguments)
      }
      }
      // 这样可获取传入的多个参数
    • 当父组件额外传入参数时

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
       this.$emit('custom', 1);
      // 父组件中 第一种方法
      <child @custom='todo($enents, 'other')'></child>

      methods: {
      todo (index, other) {
      console.log(index, other)
      }
      }

      // 父组件中 第二种方法(接收传出多个数据时)
      <child @custom='todo(arguments, 'other')'></child>

      methods: {
      todo () {
      console.log(arguments)
      }
      }
  • 事件传递多参数时event事件参数 @click=”do($event, ‘click’)”

  • 获取DOM相对于网页的位置 object.getBoundingClientRect();
  • Boolean({})与Boolean([])为true
  • 卡在了右侧的排行hover的弹窗,因为这里有个类似轮播图的东西,父元素加了overflow,只能在外面增加一个层定位用来显示信息,通过子组件传递信息到父元素获得数据和位置信息来控制这个层的显示
  • 今天进度(循环渲染真的爽,写好了动画一个类目,然后处理好所有数据一个v-for全出来了)

第7天

  • 事件传对象参数时出了点问题

    1
    2
    <li @mouseover="change({type: 0})" :class="{active: index === 0}">全部</li>
    <li @mouseover="change({type: 1})" :class="{active: index === 1}">原创</li>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //这样写没问题
    change (data) {
    this.index = data.type === undefined ? this.index : data.type
    }

    //但是如果这样写的话执行第二次时data参数就消失了,全都跳过了第一个判断
    change (data) {
    this.index = data.type || this.index
    }
  • Element.scrollIntoView()可以传参数完成平滑滚动]

    • alignToTop
      一个Boolean值:
      • 如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。
      • 如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。
    • scrollIntoViewOptions
      一个boolean或一个带有选项的object:
      1
      2
      3
      4
      {
      behavior: "auto" | "instant" | "smooth",
      block: "start" | "end",
      }
  • 在有背景图并且有透明通道的div上可以设置背景色,但background-color属性要设置在背景图下面

  • 今天出了点事,用的几个第三方接口挂了,然后又去官网抓了官方接口重写了后台
  • 因为后台代理了所有图片,跑在我这台电脑上速度还行,挂到阿里云的一兆水管上,图大多GG,然后试着上个redis会不会好点

第8天

  • 整理一下数据接口,完成了各分类的新动态和新投稿的切换
  • 部署到服务器,顺便临时升了下带宽,图片能够陆续正常加载了
  • 刚刚遇到一个很奇怪问题父组件对象的属性更新了,子组件却不更新数据(官方文档上说是对象属性的增加或删除会检测不到变化,而且我这个变化连watch deep都检测不到,见鬼了,这个组件还有个和这个变量一个类型的,同样改属性值却能刷新DOM,简直见鬼了!!!这个变量是掉进异次元了么),试了好几个办法
    • this.$forceUpdate()完美成功
    • 虽然官方有个this.$set,但文档上说的是在对象的添加或删除时使用,而且在这里我用了这个重设属性值竟然也无效
    • 使用Object.assign创建新对象并整个赋值,能刷新DOM,但是会导致刷新整个DOM(相当于整个数据从null到恢复数据,DOM整个都在闪啊我的天)
  • 现在还剩右侧电梯的排序,动漫时间线,弹幕和预览功能没写