Heim  >  Artikel  >  Web-Frontend  >  React-Technologie-Stack-Praxis einer kleinen Anwendung für die Filmsammlung

React-Technologie-Stack-Praxis einer kleinen Anwendung für die Filmsammlung

小云云
小云云Original
2017-12-18 15:43:061460Durchsuche
Dieser Artikel teilt Ihnen hauptsächlich die Praxis des Reaktionstechnologie-Stacks kleiner Anwendungen für die Filmsammlung mit und hofft, allen zu helfen.

Hauptfunktionen

  • Douban-Filminformationen durchsuchen und in MongoDB eingeben

  • Filmlistenanzeige, Klassifizierung, Suche

  • Anzeige von Filmdetails und Verwaltung von Anhängen

  • Registrierung und Anmeldung

  • Berechtigungskontrolle, normale Benutzer können sich anmelden in, Favoriten, Administratoreintrag, Änderung, Löschung

  • Benutzercenter, meine Favoritenliste

React-Technologie-Stack-Praxis einer kleinen Anwendung für die Filmsammlung

Einige Zusammenfassung

Front-End

Die Front-End-Anwendungen React, Redux und Redux-Saga fassen Redux kurz zusammen und zeichnen ein Abhängigkeitsproblem bei Front- und Rear-Schnittstellenaufrufen auf

  • Redux

Um Redux in einem Satz zusammenzufassen: Ich denke, es geht darum, den vertikalen Requisitentransfer zwischen Komponenten und die Hassliebe zu verknüpfen Die Beziehung zwischen übergeordneten und untergeordneten Komponenten wird ausgeglichen und eine vertikale Beziehung in 多个组件和一个独立出来的状态对象直接交互 umgewandelt, sodass die Codestruktur klarer aussieht.

Die Kernkonzepte Redux, Action, Reducer und Store

action就是说明我要操作一个状态了,怎么操作是reducer的事,而所有状态存储在store中,store发出动作并交由指定的reducer来处理

Redux zwingt uns dazu, unsere Operationen auf den Zustand zu standardisieren, was nur in Aktionen erfolgen kann und Reduzierer Auf diese Weise wird die ursprüngliche komplizierte Geschäftslogikverarbeitung geändert und auf Aktionen und Reduzierer beschränkt, und die Komponenten sehen sehr sauber aus. Tatsächlich ist es kompliziert, egal wo man diese komplizierte Sache platziert, aber jetzt ist es etwas klarer

Der Nachteil der Verwendung von Redux besteht darin, dass es zu umständlich ist, verschiedene Aktionen zu definieren und verschiedene Komponenten zu verbinden. . . . . Jetzt gibt es einen weiteren Mobx, ich weiß nicht, wie mächtig er ist, aber alle sind sich einig~

  • redux-saga

redux-saga wird verwendet, um asynchrone Aufrufe und andere Dinge zu verarbeiten. Häufig verwendete Generatoren sind take,takeLatest,takeEvery,put,call,fork,select. Während des Verwendungsprozesses bin ich auf ein Problem mit Schnittstellenaufrufen gestoßen interessant.

Beschreiben Sie es:

  1. hat eine Schnittstelle /api/user/checkLogin, die verwendet wird, um zu bestimmen, ob eine Anmeldung erfolgen soll. Die ComponentDidMount der äußersten -Komponenten-Trigger-Aktion, um diese Anfrage zu initiieren, und wenn der Schnittstellen-Rückgabestatus angemeldet ist, müssen Sie auch ein

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)
}
senden
  1. um Benutzerinformationen zu erhalten. Dann habe ich eine Filmdetailseitenkomponente, in der componentDidMount dieser Komponente wird die /api/movies/${id}-Schnittstelle initiiert um Filminformationen zu erhalten. Wenn der Benutzer angemeldet ist, wird auch eine Schnittstelle zum Abrufen von Filmanhangsinformationen initiiert/api/movies/${id}/attach, Der gesamte Schritt ist in einem Generator geschrieben

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)
}
  1. Der Benutzer ist angemeldet und gibt die Details ein. Der Vorgang ist normal. Wenn die Seite jedoch auf der Detailseite aktualisiert wird, ist die Schnittstelle zum Abrufen von Anhängen geöffnet nicht ausgelöst. Der Grund dafür ist, dass die checkLogin-Schnittstelle zu diesem Zeitpunkt das Ergebnis nicht zurückgegeben hat, der Status state.loginStatus immer noch falsch ist und das Obige nicht zum if

  2. geht Zuerst habe ich darüber nachgedacht, wie ich die Reihenfolge der Erträge in einigen Generatoren steuern kann, um das Problem zu lösen (wenn der Benutzer nicht angemeldet ist, senden Sie einen weiteren CHECK_LOAGIN, und der Prozess wird fortgesetzt, nachdem das Ergebnis zurückgegeben wurde), aber es gibt zweimal CHECK_LOAGIN-Aufrufe . Wenn nach der Anmeldung ein weiterer Schnittstellenaufruf erfolgt, um Benutzerinformationen abzurufen, ist dies definitiv nicht möglich.

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]))
    }
}
  1. Die letzte Methode ist die Zerlegung Die Verantwortlichkeiten des Generators ComponentWillUpdate lösen die Aktion zum Erhalten von Anhängen ordnungsgemäß aus

//将获取附件的动作从 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)
        }
}
  1. Abschließend: Verwenden Sie die Hook-Funktion der Komponente rational und nicht Verarbeiten Sie zu viele Vorgänge im Generator, um die Flexibilität zu erhöhen

Backend

Das Backend verwendet Express und Mongodb, und Redis wird ebenfalls verwendet.使用pm2来管理node应用及部署代码 . Um die Identitätsauthentifizierung in Mongodb zu aktivieren, lohnt es sich, beim Durchführen der Identitätsauthentifizierung und beim Schreiben von Komponententests im Knoten JWT + Redis für die tokenbasierte Benutzeridentitätsauthentifizierung zu verwenden 🎜>

  • Tokenbasierter Authentifizierungsprozess

Der Client initiiert eine Anmeldeanforderung

  1. Der Server überprüft die Benutzername und Passwort

  2. Nach erfolgreicher Verifizierung generiert der Server ein Token und antwortet dem Client

  3. Der Client trägt dieses Token im Header jeder nachfolgenden Anfrage

  4. Der Server muss das Token für die Schnittstelle überprüfen, die eine Authentifizierung erfordert, und sicherstellen, dass die Anfrage erfolgreich empfangen wurde

  5. Hier wird jsonwebtoken zum Generieren des Tokens verwendet.

  6. wird als Express-JWT-Verifizierungstoken verwendet (bei erfolgreicher Überprüfung werden die Tokeninformationen in request.user abgelegt).

Warum Redis verwenden?
jwt.sign(payload, secretOrPrivateKey, [options, callback])

** Wenn Sie jsonwebtoken zum Generieren eines Tokens verwenden, können Sie die Gültigkeitsdauer des Tokens angeben, und die Überprüfungsmethode von jsonwebtoken bietet auch Optionen zum Aktualisieren der Gültigkeitsdauer des Tokens
Hier wird jedoch die Middleware express_jwt verwendet , und express_jwt bietet keine Methode zum Aktualisieren des Tokens. **

Idee:

  1. Der Client fordert erfolgreich eine Anmeldung an und generiert ein Token

  2. Speichern Sie dieses Token in Redis. Legen Sie die Gültigkeitsdauer von Redis fest (z. B. 1 Stunde).

  3. Wenn eine neue Anfrage eingeht, überprüfen Sie zuerst das Token mit express_jwt, der Verifizierung ist erfolgreich, und überprüfen Sie dann, ob das Token in Redis vorhanden ist. Die Existenzanweisung ist gültig

  4. Während des Gültigkeitszeitraums kommt eine neue Anfrage vom Client, extrahieren Sie das Token und aktualisieren Sie es Gültigkeitsdauer dieses Tokens in Redis

  5. Der Client meldet sich von der Anmeldeanforderung ab und löscht dieses Token in Redis

Spezifischer Code

  • Verwenden Sie mocha + supertest + sollte, um Unit-Tests zu schreiben

Testabdeckung Ich habe alle Schnittstellen langsam geschrieben, da es keine gab Fortschrittsanforderungen. Nachdem ich eine Schnittstelle geschrieben hatte, war der Test ziemlich detailliert. Der gesamte Prozess war sehr interessant >Mocha ist ein Node-Unit-Test-Framework, ähnlich dem Front-End-Jasmine, mit ähnlicher Syntax

Supertest ist eine Bibliothek zum Testen von Node-Schnittstellen

sollte die Assertionsbibliothek von NodeJS gut lesbar sein

Ein Beispiel für Tests, es ist zu lang, deshalb werde ich es hier nicht einfügen

Verwandte Empfehlungen ::

Erkundung des internen Mechanismus von React

Wie können Komponenten in React geschrieben werden?

react.js gibt Logo-Referenz , holen Sie sich den Inhalt

Das obige ist der detaillierte Inhalt vonReact-Technologie-Stack-Praxis einer kleinen Anwendung für die Filmsammlung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn