模仿今日头条app开发遇到的问题

1,769 阅读5分钟

该项目用到的技术主要有:vue-cli + vuex + mockjs。 github地址

交互功能

  • 点击菜单栏添加按钮,进入频道管理页面,可进行频道添加删除
  • 点击header左侧邮箱图片,弹出框显示
  • 点击header右侧搜索按钮,进入搜索页面,搜索异步查询到结果进行高亮
  • 频道菜单栏切换异步查询,对应频道新闻展示
  • 新闻展示懒加载,每次展示10条数据,滑到底部再加载10条。

展示功能

这里主要讲述我在实现时,觉得以后开发中可能会经常遇到的经验问题

1.菜单栏水平方向可以滑动展示多余内容

如图所示:

这里布局如下:

这里我用的方法是:

我们给这个ul外面套着一个div(.ul-box),该div的样式如下:

.nav-container .ul-box {
    width: 100vw;
    height: 0.8rem;
    overflow-x: scroll;
}

其内部的ul的样式如下:使用弹性布局

.nav-container .ul-box .nav-ul {
    line-height: 0.8rem;
    display: -webkit-box; 
    display: flex;
    height: 0.8rem;
    margin-right: 0.2rem;
}

第二种方法,使用white-space: norwrap

这里不需要更改上面最外层div的样式,只需要更改ul的样式,使用white-space: norwrap

.nav-container .ul-box .nav-ul {
    line-height: 0.8rem;
    white-space: norwrap//划重点就是这句话
    height: 0.8rem;
    margin-right: 0.2rem;
}

2.新闻卡片,不同类型的卡片不同的布局

这里的新闻有四种不同布局

  • 没有图片的新闻
  • 有一个图片非广告类新闻
  • 有三张图片的非广告类新闻
  • 广告

针对这四种不同类型的卡片,我的区分是首先我觉得后端可能给我的数据只会分新闻和广告,所以我用一个字段判断是新闻还是广告,然后对新闻就是通过判断该条新闻的图片个数,来进一步确定不同布局。

项目遇到的奇奇怪怪的bug和注意事项

1. 对router-link添加点击事件不起作用

  <router-link @click.native="changeTab(item.id)" :to= "{path: '/home/' + item.id}" tag="a" :data-id="item.id" :class="{selected: curIndex === item.id}">{{item.name}}</router-link>

这里需要给这个点击事件后面加上.native,加上这个之后,就将这个vue组件转为普通的html元素。给vue组件绑定原生事件就需要.native修饰v-on,否则无法注册成功

2.header布局,左侧元素float:left,让中间元素居中,我发现浮动的元素会影响中间元素 其布局图就是这样:

由于我一般情况下是能不用定位就不用,这里我第一想法是父元素设置text-align:center,左边元素浮动即可,浮动元素脱离文档流啊。。。嗯。。想法很好,然而我发现左浮的元素竟然占空间,中间的元素明显往右移动了很多。。。忍无可忍,我使用了定位,果然定位真是厉害。这里我就很有点疑惑了,不都是脱离文档流吗,咋会有不一样的效果。

通过查阅资料发现,css中的脱离文档流是将元素从普通的布局排版中拿走,这样其他元素在页面布局时,会忽略脱离文档流的元素。但是注意同样是脱离文档流,浮动的元素和定位的元素还是有区别的:
浮动元素:使用浮动的元素,虽然该元素已经脱离文档流了,但是页面中其他盒子内的文本依然会为这个元素让出位置
定位元素:页面中的其他元素会彻底无视

示例: 分别对div1使用浮动和绝对定位,其效果差如下

<div class="header">
    <div class="left">div1</div>
    <div class="center">div2</div>
</div>
.header .left {
        /* float: left; */
        position: absolute;
        left: 0;
        background: #f00;
    }
.header .center {
    background: #0ff;
}

float:left;

position:absolute;
3.关键词搜索高亮

一开始的写法是:

let exchangeKey = '<highlight>' + key + '</highlight>'
arr[index].title = arr[index].title.replace(key, exchangeKey)//key是用户输入的内容

比较懂正则的应该发现,我忘记全局匹配了,这个点真的需要注意考虑全面,一开始我写的假数据中一句话中也不会有重复的词,所以也没发现,一直到后期看正则表达式才发现这个点。 进一步修改为:

let reg = new RegExp("(" + key + ")", "ig");
arr[index].title = arr[index].title.replace(reg, '<highlight>$1</highlight>')

这下就没有啥问题了

4.去掉url上的#
在目录router/index.js里加上mode: 'history'
vue-router有两种模式(这两种模式的区别,以及应用场景还需要进一步学习和总结)

  • hash
  • history

5.vuex的使用
这里不赘述,之前总结了

6.mock的使用
见其他总结

7.返回上一页

常见的返回上一页的方法有:

  • window.history.go(-1);
  • window.history.back(-1);

进入下一页的方法有:

  • window.history.forward()

以上的方法都会刷新页面,我们的项目中使用了vuex,所以刷新是不能够的,请使用路由的跳转

8.将mock.js放入mock文件夹内,再在store文件夹里import路径会出错
这个问题暂时没有解决,就还是将mock.js放在mock文件夹外了,但是看着真是不舒服

9.使用mapState只能读state里的值,不可以进行修改
修改请在actions.js或者mutations.js里修改,或者使用store.state取值修改

10.npm run build后dist文件夹里index.html找不到对应静态资源

改config文件里的index.js

11.新闻消息懒加载
懒加载主要是监听window.onscroll事件来处理,这里注意滑动到底部之后,会发现一直会触发,这样会出现抖屏的现象,所以这里我是使用一个canGetMoreList标志位进行判断,只有当异步请求成功之后canGetMoreList为true。判断滑到底部且canGetMoreList为true时才发送异步请求。

window.onscroll = function () {
    var scrollT = document.documentElement.scrollTop || document.body.scrollTop;
    var scrollH = document.documentElement.scrollHeight || document.body.scrollHeight;
    var clientH = document.documentElement.clientHeight || document.body.clientHeight; 
    if (scrollT >= scrollH - clientH && store.state.canGetMoreList) {
        this.pageNum++
        store.state.showMoreFlag = true
        e.state.canGetMoreList = false
        setTimeout (function () {
            this.getList(this.curIndex)
        }.bind(this), 200)
    }
}.bind(this)

项目总结

每一次做一个完整的项目就好像是一个扫盲的过程,只有在遇到问题的时候才知道自己有多么的无知,给自己列一个下一步的学习计划:

  • 网络方面的知识
  • 正则表达式的学习
  • webpack的配置学习