一个实战项目的开发——知乎日报

时间:2021-06-04 20:08:23

    作为第一次的一个实战项目,我采用的是vue-cli,webpack等技术来作为项目的基石,先上个最终项目的截图吧。接下来,我将记录,我在做项目遇到的问题,以及如何填的坑。

  一个实战项目的开发——知乎日报

  这个项目是一个单页应用,简单来说就是一个不需要路由的单页面,整个页面分三个部分,第一部分是菜单,第二部分是文章列表,第三部分是文章内容和评论;再来分析下整个项目的组成部分:

一个实战项目的开发——知乎日报src目录下存放的就是我们自己写的自定义内容了哈,components目录下是两个组件,APP.vue作为我们的项目根组件,directives目录下,就我们开发的一个转换时间格式的自定义指令,libs目录下是我们开发的常用工具类,用来封装axios插件的,main.js作为我们整个项目的主入口文件,proxy.js作为代理。

  知乎日报的接口我是在网上找到的,在此感谢大大们的不懈付出哈。由于存在跨域限制,无法直接在前端获取到数据,所以,我们在这里需要用node.js开发一个代理(跨域限制是服务端的一个行为,当开启对某些域名的访问限制之后,只有同域名下或指定域下的页面可以调用,这样相对安全,图片也可以防盗链。跨域限制一般只在浏览器端存在,使用代理是开发过程中常见的一种解决方案),代理的核心就是在返回的头部添加一项Access-Control-Allow-Origin为"*",也就是允许所以的域名访问。最后,在终端使用Node.js启动代理服务,  node proxy.js  如果成功,会输出两行日志接口代理运行在 http://127.0.0.1:8010/
图片代理运行在 http://127.0.0.1:8011/ 。然后,就来开发我们的工具类,也就是对axios的封装,写在我们的util.js中, 

// Ajax 通用配置
Util.ajax = axios.create({
    baseURL: Util.apiPath
});

// 添加响应拦截器
Util.ajax.interceptors.response.use(res => {
    return res.data;
});

export default Util;

完成上面的两步,我们就可以专注我们的页面开发了。

  在APP.vue中,写HTML结构,导入组件,注册组件,一气呵成。搭建好基本页面结构就来具体地对组件进行开发。

  “主题日报”下有子类列表,默认是收起的,点击主题日报就可以切换展开和收起的状态,这点我们是用@click="showThems"=!showThems来做到的,并使用thems来循环渲染子类目。

 <div class="daily-list" ref="list">
            <template v-if="type === 'recommend'">
                <div v-for="list in recommendList" :key="list">
                    <div class="daily-date">{{ formatDay(list.date) }}</div>
                    <Item
                        v-for="item in list.stories"
                        :data="item"
                        :key="item.id"
                        @click.native="handleClick(item.id)"></Item>
                </div>

通过点击事件,将ID属性值传到对应的组件,其组件内再对应的加载对应的数组,以此来达到动态加载对应数据的目的。


handleToTheme (id) {
                this.type = 'daily';
                this.themeId = id;
                this.list = [];
                $.ajax.get('theme/' + id).then(res => {
                    this.list = res.stories
                        .filter(item => item.type !== 1);
                })
            },

具体来说,也就是在父组件内:把Item组件上的ID传递给daily-drticle组件,然后用v-bind绑定。

 getArticle () {
                $.ajax.get('news/' + this.id).then(res => {
                    res.body = res.body
                        .replace(/src="http/g, 'src="' + $.imgPath + 'http');
                    res.body = res.body
                        .replace(/src="https/g, 'src="' + $.imgPath + 'https');
                    this.data = res;
                    window.scrollTo(0, 0);
                    this.getComments();
                })

在子组件内,用props接收数据。以此来达到在组件间传递参数的目的,如果ID改变,重新执行获取文章的函数。

 mounted () {
            this.getRecommendList();
            this.getThemes();
            const $list = this.$refs.list;
            $list.addEventListener('scroll', () => {
                if (this.type === 'daily' || this.isLoading) return;
                if
                (
                    $list.scrollTop
                    + document.body.clientHeight
                    >= $list.scrollHeight
                )
                {
                    this.dailyTime -= 86400000;
                    this.getRecommendList();
                }
            });
        }

每次滑到底部的时候,获取前一天的资讯,这里监听子组件的DOM事件,要在父组件内,子组件的模板上写  ref="list" 然后使用 const $list=this.$refs.list,获取到子组件的DOM,最后再绑定事件,写对应要执行的函数。

  一个在实际开发中,经常会用到的思路,关于组件的解耦:我们从父组件获取传递过来的id,通过这个id用axios的ajax方法去获取对应id的其他数据,而不是直接将全部的数组传递给子组件。

  总体上说来,这个项目并不是很难,所开发的组件都只有两个,但是其中所涉及的方面,却是vue的大部分核心内容,包括axios的基本使用,组件间的传值,ES6模块化的运用以及一些常用API的使用。属于一个入门的项目吧,我计划下一次项目把vue全家桶用上。那么这个项目,我已经上传至我的github:github