初看到掘金 - 2020年度人气创作者榜单这个网站,感觉整体界面效果给我一种清爽的感觉,于是花了点时间琢磨如何实现。目前实现的功能有:列表展示,搜索,无限加载(与原网站有些区别,加了loading效果),活动介绍,tab切换。通过这些,我对vue3.0的composition api有了一定的认知,下面让我们来看看吧!
ps:个人认为原网站应该是使用react.js写的
直接请求该网站的数据接口,应该是会报跨域问题的。于是我想了一个办法,就是通过node.js
来爬取数据。下面来看看代码:
node后端爬取数据
代码如下:
const superagent = require('superagent');
const express = require('express');
const app = express();
const port = 8081;
function isObject(value) {
return value && typeof value === 'object';
}
function getApi(url, params,method) {
return new Promise((resolve) => {
if (!isObject(params)) {
return resolve(setResponse(400, null, '请传入参数!'));
} else {
let paramMethod = method.toLowerCase() === 'post' ? 'send' : 'query';
superagent(method,url)[paramMethod](params).set('X-Agent', 'Juejin/Web').end((err, supRes) => {
if (err) {
return resolve(setResponse(400, null, err));
}
let data = JSON.parse(supRes.text);
resolve(setResponse(data.err_no === 0 ? 200 : data.err_no, data.data, data.err_msg));
});
}
})
}
app.use(express.json());
app.all("*", function (req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
if (req.method.toLowerCase() == 'options') {
res.send(200);
} else {
next();
}
});
function setResponse(code, data, message) {
return {
code: code,
data: data,
message: message
}
}
app.post('/info', (req, res) => {
const params = req.body;
getApi('https://api.juejin.cn/list_api/v1/annual/info', params,'post').then(data => {
res.send(JSON.stringify(data));
})
})
app.post('/list', (req, res) => {
const params = req.body;
getApi('https://api.juejin.cn/list_api/v1/annual/list', params,'post').then(data => {
res.send(JSON.stringify(data));
});
})
app.get('/user',(req,res) => {
const params = req.query;
getApi('https://api.juejin.cn/user_api/v1/user/get',params,'get').then(data => {
res.send(JSON.stringify(data));
})
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
以上只是爬了主要的三个接口,如list
接口,info
接口以及user
接口。当然还有登录功能没有写,掘金应该是通过cookie
技术去实现判断用户是否登录的,当从掘金打开,跳往该网站,会向浏览器的cookie
存储用户相关登录信息。如下图所示:
这一个功能的实现思路知道即可,源码不会实现。然后在该网站去获取cookie
并传递参数给user
接口既可以获取登录相关信息。
以上代码思路也很简单,就是通过搭建一个本地服务器,然后爬取该网站的三个主要的接口,主要使用了superagent
这个库来进行爬取。相关API可以参考superagent文档。然后就是允许跨域的设置,用了node
框架express
。没什么技术难点。
web前端
技术点:vue3.0,typescript,vue-cli4.0,axios,less
首先分析一下页面,主要分为首页和活动介绍页。其中Header
和Footer
组件作为一个公共组件,这是毋庸置疑的。当然,这两个组件的代码也比较简单,可以不做分析。如下:
Header
显然,Header
组件主要考查CSS
布局,好吧,虽然可以说是模仿写了一遍布局(所有布局都是同理,没什么好说的),但也算是抄袭了(PS:希望掘金技术团队不介意吧)。
Footer
这个组件难度也不大,就是把导航数据归纳到一起了而已。
活动介绍页面也比较简单,就一个tab
组件,然后其它都是图片布局。
当然后续代码我就不一一展示了,我主要总结一下所用到的技术知识点。
首先是vuex
,vue2
熟练使用的话,其实vue3
语法也差别不大。
import { useStore } from "vuex";
// store.state
// store.dispath(方法名,数据)
主要如果子组件想通过事件传递给父组件,则需要通过mitt
插件,譬如搜索组件的代码实现如下:
import mitt from 'mitt';
export const emitter = mitt();
export default {
setup() {
const state = reactive({
keyword:""
})
const refState = toRefs(state);
const onSearch = () => {
if(!state.keyword)return alert('请输入你喜欢的作者名!');
//传递给父组件
emitter.emit('on-search',state.keyword);
}
return {
...refState,
onSearch
};
},
};
其它的都是vue3.0
的语法了,比如watch
监听等等,更多源码在这里。
PS:不知道到时间了掘金官方会不会停止相关数据接口的服务,所以下一步,我可能会考虑写静态数据,然后把axios封装一下,当然代码还有些粗糙,因为实现的有些匆忙,后续会做优化。
最后,附上部分效果图: