Cet article partage principalement avec vous la pratique de la pile technologique React d'une petite application pour la collection de films, j'espère qu'il pourra vous aider.
Explorer les informations sur le film Douban et les saisir dans MongoDB
Affichage de la liste de films, classification, recherche
Affichage des détails du film et gestion des pièces jointes
Inscription et connexion
Contrôle des autorisations, les utilisateurs ordinaires peuvent se connecter dans, Favoris, saisie administrateur, modification, suppression
Centre utilisateur, ma liste de favoris
Le front-end utilise React, Redux et Redux-saga Résumons brièvement Redux et enregistrons un problème de dépendance sur les appels d'interface avant et arrière.
Pour résumer redux en une phrase, je pense que c'est pour emmêler le transfert d'accessoires verticaux entre les composants et l'amour-haine relation entre les composants parent et enfant. Elle est égalisée et une relation verticale est transformée en 多个组件和一个独立出来的状态对象直接交互
, de sorte que la structure du code semble plus claire.
Les concepts fondamentaux de redux, d'action, de réducteur et de magasin
action就是说明我要操作一个状态了,怎么操作是reducer的事,而所有状态存储在store中,store发出动作并交由指定的reducer来处理
redux nous oblige à standardiser nos opérations sur l'état, ce qui ne peut être effectué que dans des actions et les réducteurs. De cette façon, le traitement logique métier complexe d'origine est modifié et limité aux actions et aux réducteurs, et les composants semblent très propres. En fait, c'est compliqué peu importe où mettre cette chose compliquée, mais maintenant c'est un peu plus clair
L'inconvénient d'utiliser redux est qu'il est trop fastidieux de définir diverses actions et de connecter différents composants. . . . . Maintenant, il y a un autre Mobx, je ne sais pas à quel point il est puissant, mais tout le monde est d'accord~
redux-saga est utilisé pour gérer les appels asynchrones et d'autres choses, utiliser des générateurs pour rendre le code asynchrone plus concis. Les plus couramment utilisés sont take,takeLatest,takeEvery,put,call,fork,select
Au cours du processus d'utilisation, j'ai rencontré un problème de dépendances entre les appels d'interface. >
/api/user/checkLogin, qui est utilisée pour déterminer s'il faut se connecter. Le composantDidMount du plus externe Composant
function* checkLogin() { const res = yield Util.fetch('/api/user/checkLogin') yield put(recieveCheckLogin(!res.code)) if (!res.code) { //已登录 yield put(fetchUinfo()) } } export function* watchCheckLogin() { yield takeLatest(CHECK_LOAGIN, checkLogin) }
componentDidMount de ce composant, l'interface /api/movies/${id}
sera lancée pour obtenir des informations sur le film. . Si l'utilisateur est connecté, une interface permettant d'obtenir les informations sur les pièces jointes du film sera également lancée/api/movies/${id}/attach
, L'étape entière est écrite dans un générateur
function* getItemMovie(id) { return yield Util.fetch(`/api/movies/${id}`) } function* getMovieAttach(id) { return yield Util.fetch(`/api/movies/${id}/attach`) } function* getMovieInfo(action) { const { movieId } = action let { login } = yield select(state => state.loginStatus) const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) if (res.data[0].attachId && login) { const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } } export function* watchLoadItemMovie() { yield takeLatest(LOAD_ITEM_MOVIE, getMovieInfo) }
state.loginStatus
function* getMovieInfo(action) { const { movieId } = action let { login } = yield select(state => state.loginStatus) const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) // if (!login) { // //刷新页面的时候,如果此时checklogin接口还没返回数据或还没发出,应触发一个checklogin // //checklogin返回后才能得到login状态 // yield put({ // type: CHECK_LOAGIN // }) // const ret = yield take(RECIEVE_CHECK_LOAGIN) // login = ret.loginStatus // } if (res.data[0].attachId && login) { const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } }
//将获取附件的动作从 getMovieInfo这个generator中分离出来 function* getMovieInfo(action) { const { movieId } = action const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) } function* watchLoadItemMovie() { yield takeLatest(LOAD_ITEM_MOVIE, getMovieInfo) } function* watchLoadAttach() { while (true) { const { movieId } = yield take(LOAD_MOVIE_ATTACH) const { attachId } = yield select(state => state.detail.movieInfo) const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } } //组件中 componentWillUpdate(nextProps) { if (nextProps.loginStatus && (nextProps.movieInfo!==this.props.movieInfo)) { //是登录状态,并且movieInfo已经返回时 const { id } = this.props.match.params this.props.loadMovieAttach(id) } }
使用pm2来管理node应用及部署代码
jwt.sign(payload, secretOrPrivateKey, [options, callback])
express_jwt({ secret: SECRET, getToken: (req)=> { if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') { return req.headers.authorization.split(' ')[1]; } else if (req.query && req.query.token) { return req.query.token; } return null; } }
** Lorsque vous utilisez jsonwebtoken pour générer un jeton, vous pouvez spécifier la période de validité du jeton, et la méthode de vérification de jsonwebtoken fournit également des options pour mettre à jour la période de validité du jeton
Mais le middleware express_jwt est utilisé ici. , et express_jwt ne fournit pas de méthode pour actualiser le jeton. **
Idée :
Le client demande une connexion avec succès et génère un jeton
Enregistrez ce token dans redis, définissez la période de validité de redis (par exemple, 1h)
Lorsqu'une nouvelle demande arrive, vérifiez d'abord le token avec express_jwt, la vérification réussit, puis vérifiez si le jeton existe dans redis, la déclaration d'existence est valide
Pendant la période de validité, une nouvelle demande vient du client, extrayez le jeton et mettez à jour le période de validité de ce token dans redis
Le client se déconnecte de la demande de connexion et supprime ce token dans redis
Code spécifique
Couverture des tests J'ai écrit toutes les interfaces Pendant le développement, je les ai écrites lentement car il n'y en avait pas. exigences de progression. Après avoir écrit une interface, j'ai écrit un test. Une fois le test réussi, j'ai ensuite ajusté l'interface sur le front-end
mocha est un framework de tests unitaires de nœuds, similaire au jasmine frontal, avec une syntaxe similaire
supertest est une bibliothèque utilisée pour tester les interfaces de nœuds
Bibliothèque d'assertions nodejs, très lisible
Un exemple de test, c'est trop long, donc je ne le mettrai pas iciRecommandations associées :Explorer le mécanisme interne de React
Quelles sont les façons d'écrire des composants dans React
react.js donne la référence du logo , récupérez le contenu
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!