javascript react - توجيه العميل(باستخدام موجّه الاستجابة)والتوجيه من جانب الخادم




paths react-router-dom (3)

لقد كنت أفكر وأنا في حيرة من أمري مع التوجيه بين العميل والخادم. لنفترض أنني استخدم ReactJS للعرض من جانب الخادم قبل إرسال الطلب مرة أخرى إلى متصفح الويب ، واستخدام موجه الاستجابة كجهاز توجيه من جانب العميل للتبديل بين الصفحات دون التحديث كـ SPA.

ما يتبادر إلى الذهن هو:

  • كيف يتم تفسير الطرق؟ على سبيل المثال ، طلب من الصفحة الرئيسية ( /home ) إلى صفحة المشاركات ( /posts )
  • أين يذهب التوجيه ، من جانب الخادم أو العميل؟
  • كيف تعرف كيف تتم معالجتها؟

Answers

ملاحظة ، هذه الإجابة تغطي React Router version 0.13.x - يبدو أن الإصدار القادم 1.0 سيحتوي على تفاصيل تنفيذ مختلفة بشكل ملحوظ

الخادم

هذا هو server.js الحد الأدنى مع رد فعل الموجه:

var express = require('express')
var React = require('react')
var Router = require('react-router')

var routes = require('./routes')

var app = express()

// ...express config...

app.use(function(req, res, next) {
  var router = Router.create({location: req.url, routes: routes})
  router.run(function(Handler, state) {
    var html = React.renderToString(<Handler/>)
    return res.render('react_page', {html: html})
  })
})

حيث تصدر وحدة routes قائمة من المسارات:

var React = require('react')
var {DefaultRoute, NotFoundRoute, Route} = require('react-router')

module.exports = [
  <Route path="/" handler={require('./components/App')}>
    {/* ... */}
  </Route>
]

في كل مرة يتم فيها تقديم طلب إلى الخادم ، تقوم بإنشاء مثيل Router لمرة واحدة يتم تكوينه باستخدام عنوان URL الوارد كموقع ثابت ، والذي يتم حله مقابل شجرة المسارات لإعداد المسارات الملائمة المطابقة ، مع معاودة الاتصال بالأعلى يتم تقديم معالج مسار المستوى وسجل لطرق الأطفال التي تتطابق مع كل مستوى. هذا ما يتم استشارته عند استخدام المكون <RouteHandler> داخل مكون توجيه المسار لعرض مسار تابع تمت مطابقته.

إذا تم إيقاف تشغيل جافا سكريبت ، أو إذا كان التحميل بطيئًا ، فستؤدي أي روابط ينقرون عليها إلى الوصول إلى الخادم مرة أخرى ، ويتم حلها مرة أخرى على النحو الوارد أعلاه.

زبون

هذا هو الحد الأدنى من client.js مع موجّه الاستجابة (إعادة استخدام نفس وحدة التوجيهات):

var React = require('react')
var Router = require('react-router')

var routes = require('./routes')

Router.run(routes, Router.HistoryLocation, function(Handler, state) {
  React.render(<Handler/>, document.body)
})

عند الاتصال بـ Router.run() ، يقوم بإنشاء مثيل Router لك خلف الكواليس ، والتي يتم إعادة استخدامها في كل مرة تتنقل فيها حول التطبيق ، حيث يمكن أن يكون عنوان URL ديناميكيًا على العميل ، بدلاً من الخادم الموجود على الخادم طلب واحد لديه عنوان URL ثابت.

في هذه الحالة ، نحن نستخدم HistoryLocation ، الذي يستخدم History API للتأكد من أن الشيء الصحيح يحدث عندما تضغط على زر الرجوع / الخلف. هناك أيضًا HashLocation الذي يغيّر hash عنوان URL لإدخال مدخلات التاريخ ويستمع إلى الحدث window.onhashchange لتشغيل التنقل.

عند استخدام مكون <Link> الخاص بـ react-router ، فإنك تقوم بإعطائه اسم المسار ، بالإضافة إلى أي params وبيانات query يحتاجها المسار. يحتوي <a> المقدمة بواسطة هذا المكون على معالج onClick الذي يستدعي في النهاية router.transitionTo() على مثيل الموجه مع الدعائم التي أعطيتها الرابط ، والتي تبدو كالتالي:

  /**
   * Transitions to the URL specified in the arguments by pushing
   * a new URL onto the history stack.
   */
  transitionTo: function (to, params, query) {
    var path = this.makePath(to, params, query);

    if (pendingTransition) {
      // Replace so pending location does not stay in history.
      location.replace(path);
    } else {
      location.push(path);
    }
  },

بالنسبة لرابط منتظم ، فإن هذا الأمر في نهاية المطاف يستدعي location.push() في أي نوع من أنواع المواقع التي تستخدمها ، والذي يتعامل مع تفاصيل إعداد السجل بحيث يعمل التنقل باستخدام الأزرار الخلفية router.handleLocationChange() ، ثم يتصل مرة أخرى إلى router.handleLocationChange() إلى اسمح للموجه بمعرفة أنه يمكن المضي قدمًا في الانتقال إلى مسار عنوان URL الجديد.

ثم يقوم الموجه باستدعاء طريقة router.dispatch() الخاصة به مع عنوان URL الجديد ، والذي يعالج تفاصيل تحديد أي من المسارات التي تمت تهيئتها تتطابق مع عنوان URL ، ثم يدعو أي خطافات انتقال موجودة للمسارات المطابقة. يمكنك تنفيذ خطافات النقل هذه على أي من معالجات المسار الخاص بك لاتخاذ بعض الإجراء عندما يكون التوجيه على وشك الانتقال بعيدًا عن أو الانتقال إليه ، مع القدرة على إحباط الانتقال إذا لم تكن الأمور على النحو الذي تفضله.

إذا لم يتم إحباط عملية النقل ، فإن الخطوة الأخيرة هي استدعاء معاودة الاتصال التي قدمتها إلى Router.run() مع مكون معالج المستوى الأعلى وكائن حالة يحتوي على كافة تفاصيل عنوان URL Router.run() المطابقة. إن مكون معالج المستوى الأعلى هو في الواقع مثيل Router نفسه ، والذي يعالج عرض معالج المسارات الأكثر شيوعًا والذي تمت مطابقته.

تتم إعادة تشغيل العملية المذكورة أعلاه في كل مرة تقوم فيها بالانتقال إلى عنوان URL جديد على العميل.

مشاريع المثال


مع 1.0 ، يعتمد React-Router على وحدة history باعتبارها peerDependency. هذه الوحدة تتعامل مع التوجيه في المتصفح. بشكل افتراضي ، يستخدم pushState -Router واجهة برمجة تطبيقات سجل HTML5 ( pushState ، replaceState ) ، ولكن يمكنك تهيئتها لاستخدام التوجيه المستند إلى التجزئة (انظر أدناه)

يتم الآن معالجة الطريق خلف الكواليس ، ويرسل ReactRouter الدعائم الجديدة لأسفل إلى معالجات المسار عندما يتغير المسار. يحتوي جهاز التوجيه على onUpdate رد onUpdate جديدة عند إجراء onUpdate عند تغيير المسار ، أو مفيد لتتبع مشاهدة الصفحة ، أو تحديث <title> ، على سبيل المثال.

العميل (توجيه HTML5)

import {Router} from 'react-router'
import routes from './routes'

var el = document.getElementById('root')

function track(){
  // ...
}

// routes can be children
render(<Router onUpdate={track}>{routes}</Router>, el)

العميل (التوجيه المستند إلى التجزئة)

import {Router} from 'react-router'
import {createHashHistory} from 'history'
import routes from './routes'

var el = document.getElementById('root')

var history = createHashHistory()

// or routes can be a prop
render(<Router routes={routes} history={history}></Router>, el)

الخادم

على الخادم ، يمكننا استخدام ReactRouter.match ، وهذا مأخوذ من دليل تقديم الخادم

import { renderToString } from 'react-dom/server'
import { match, RoutingContext } from 'react-router'
import routes from './routes'

app.get('*', function(req, res) {
  // Note that req.url here should be the full URL path from
  // the original request, including the query string.
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
      res.status(200).send(renderToString(<RoutingContext {...renderProps} />))
    } else {
      res.status(404).send('Not found')
    }
  })
})

Personally, I would not place too much emphasis on such "folk wisdom." What may have been true in the past might well not be true now. I would assume that all of the operations relating to a web-page's interpretation and rendering are fully asynchronous ("fetching" something and "acting upon it" are two entirely different things that might be being handled by different threads, etc. ), and in any case entirely beyond your control or your concern.

I'd put CSS references in the "head" portion of the document, along with any references to external scripts. (Some scripts may demand to be placed in the body, and if so, oblige them.)

أبعد من ذلك ... إذا لاحظت أن "هذا يبدو أسرع / أبطأ من ذلك ، على هذا / ذلك المتصفح ،" تعامل مع هذه الملاحظة كفضول مثير ولكن غير ذي صلة ولا تجعله يؤثر على قرارات التصميم الخاصة بك. تتغير الكثير من الأشياء بسرعة كبيرة. (أي شخص يرغب في وضع أي رهانات على عدد الدقائق التي سيأتي قبل أن يخرج فريق Firefox مع إصدار مؤقت آخر لمنتجه؟ نعم ، أنا لا.)





javascript reactjs routes react-router url-routing