मैं purescript-routing लाइब्रेरी का उपयोग करके, PureScript में पुशस्टेट रूटिंग करने का प्रयास कर रहा हूं। इसे हल करने में मदद करने के लिए, मैंने निम्नलिखित न्यूनतम उदाहरण बनाया है:

module Main where

import Prelude

import Data.Foldable (oneOf)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Effect (Effect)
import Effect.Console (log)
import Flame (Html, QuerySelector(..))
import Flame.Application.NoEffects as FAN
import Flame.HTML.Attribute as HA
import Flame.HTML.Element as HE
import Routing.Match (Match, end, int, lit, root)
import Routing.PushState (makeInterface, matches)
import Signal.Channel (send)

type Model = {
  route :: Route
}

data Message = ChangeRoute Route

data Route
  = RouteOne
  | RouteTwo
  | RouteThree Int
  | Root

derive instance genericRoute :: Generic Route _
instance showRoute :: Show Route where
  show = genericShow

route :: Match Route
route = root *> oneOf
  [ Root <$ end
  , RouteOne <$ lit "route-1" <* end
  , RouteTwo <$ lit "route-2" <* end
  , RouteThree <$> (lit "route-3" *> int)
  ]

init :: Model
init = { route: Root }

update :: Model -> Message -> Model
update model = case _ of
  ChangeRoute x -> model { route = x }

view :: Model -> Html Message
view model = HE.main "main" $
  [ HE.p_ ("Route: " <> show model.route)
  , HE.ul_
    [ HE.li_
      [ HE.a [ HA.href "/route-1" ] "route 1"
      ]
    , HE.li_
      [ HE.a [ HA.href "/route-2" ] "route 2"
      ]
    , HE.li_
      [ HE.a [ HA.href "/route-3/123" ] "route 3"
      ]
    ]
  ]

main :: Effect Unit
main = do
  nav <- makeInterface

  flameChannel <- FAN.mount (QuerySelector "main")
    { init
    , update
    , view
    }

  void $ nav # matches route \oldRoute newRoute -> do
    log $ show oldRoute <> " -> " <> show newRoute
    send flameChannel [ ChangeRoute newRoute ]

क्या काम करता है:

  • रूट पार्सिंग
  • कंसोल में वर्तमान मार्ग को प्रिंट करना

क्या काम नहीं करता है: डीओएम में एक लिंक पर क्लिक करने से एप्लिकेशन को सिग्नल भेजे जाने के बजाय पेज लोड द्वारा नियंत्रित किया जाता है।

ब्राउज़र पेज लोड के विपरीत, फ्लेम को भेजे जाने वाले सिग्नल में एक लिंक परिणाम पर क्लिक करने के लिए कौन से कोड परिवर्तन/जोड़ने की आवश्यकता है? क्या मेरा सामान्य दृष्टिकोण भी सही है?

मैंने purescript-routing documentation का उपयोग करने का प्रयास किया है। और प्योरस्क्रिप्ट-रूटिंग टेस्ट समझ हासिल करने के लिए, लेकिन न तो एक पूरा उदाहरण दिखाएं (क्लिक करने योग्य URL सहित)। मैंने RoutingPushHalogenClassic PureScript कुकबुक कोड से भी काम करने की कोशिश की है, लेकिन यह फ्लेम पर लागू नहीं लगता।

1
user4301448 6 फरवरी 2021, 00:42

1 उत्तर

सबसे बढ़िया उत्तर

इसे पूरा करने का यह एक तरीका है:

module Main where

import Prelude
import Data.Foldable (oneOf)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..), isNothing)
import Debug.Trace (spy)
import Effect (Effect)
import Effect.Console (log)
import Flame (Html, QuerySelector(..))
import Flame.Application.NoEffects as FAN
import Flame.HTML.Attribute as HA
import Flame.HTML.Element as HE
import Foreign (unsafeToForeign)
import Routing.Match (Match, end, int, lit, root)
import Routing.PushState (PushStateInterface, makeInterface, matches)
import Signal.Channel (Channel, send)
import Web.Event.Event (preventDefault)

type Model
  = { navInterface :: PushStateInterface
    , route :: Route
    }

data Message
  = ChangeRouteInternal Route
  | ChangeRouteExternal Route

data Route
  = RouteOne
  | RouteTwo
  | RouteThree Int
  | Root

derive instance genericRoute :: Generic Route _

instance showRoute :: Show Route where
  show = genericShow

route :: Match Route
route =
  root
    *> oneOf
        [ Root <$ end
        , RouteOne <$ lit "route-1" <* end
        , RouteTwo <$ lit "route-2" <* end
        , RouteThree <$> (lit "route-3" *> int) <* end
        ]

init :: PushStateInterface -> Model
init nav = { navInterface: nav, route: Root }

update :: Model -> Message -> Model
update model = case _ of
  ChangeRouteInternal x -> spy "ChangeRouteInternal" model { route = x }
  ChangeRouteExternal x -> spy "ChangeRouteExternal" model { route = x }

view :: Model -> Html Message
view model =
  HE.main "main"
    $ [ HE.p_ ("Route: " <> show model.route)
      , HE.ul_
          [ HE.li_
              [ HE.a (routeAnchorAttributes (ChangeRouteInternal RouteOne)) "route 1"
              ]
          , HE.li_
              [ HE.a (routeAnchorAttributes (ChangeRouteInternal RouteTwo)) "route 2"
              ]
          , HE.li_
              [ HE.a (routeAnchorAttributes (ChangeRouteInternal (RouteThree 123))) "route 3"
              ]
          ]
      ]
  where
  routeAnchorAttributes = case _ of
    ChangeRouteInternal anchorRoute -> [ HA.href (routeToUrl anchorRoute), onClick_ anchorRoute ]
    _ -> []

  -- Based on keypress example at:
  -- https://github.com/easafe/purescript-flame/blob/master/test/Basic/EffectList.purs
  onClick_ clickedRoute =
    HA.createRawEvent "click"
      $ \event -> do
          preventDefault event
          model.navInterface.pushState (unsafeToForeign {}) (routeToUrl clickedRoute)
          pure $ Just (ChangeRouteInternal clickedRoute)

routeToUrl :: Route -> String
routeToUrl = case _ of
  Root -> "/"
  RouteOne -> "/route-1"
  RouteTwo -> "/route-2"
  RouteThree n -> "/route-3/" <> (show n)

routeMatch :: Match Route -> Channel (Array Message) -> PushStateInterface -> Effect Unit
routeMatch m chan =
  void
    <$> matches m \oldRoute newRoute -> do
        log $ show oldRoute <> " -> " <> show newRoute
        if isNothing oldRoute then
          send chan [ ChangeRouteExternal newRoute ]
        else
          pure unit

main :: Effect Unit
main = do
  nav <- makeInterface
  flameChannel <-
    FAN.mount (QuerySelector "main")
      { init: init nav
      , update
      , view
      }
  routeMatch route flameChannel nav
  • इस कोड में अलग-अलग Message एप्लिकेशन के अंदर से बाहर होने वाले रूट परिवर्तन के लिए ठोस प्रकार हैं, यानी एड्रेस बार में टाइप करने वाले उपयोगकर्ता से, बाहरी लिंक से एप्लिकेशन लोड करना आदि। यह आवश्यक नहीं है, लेकिन मैं चाहता था यह उजागर करने के लिए कि इन परिस्थितियों के लिए तर्क और कोड पथ भिन्न हैं।
  • routeMatch बाहरी रूटिंग परिवर्तनों को संभालता है, onClick_ आंतरिक के लिए है और फ्लेम के अपने createRawEvent फ़ंक्शन।
  • जबकि फ्लेम डॉक्स क्लिक हैंडलिंग और preventDefault को कवर नहीं करता, मुझे की कैप्चर का यह परीक्षण onClick_ बनाते समय बहुत मददगार होता है।
  • संदेश और आंतरिक स्थिति में परिवर्तन देखने के लिए डेवलपर टूल कंसोल खोलें।
0
user4301448 9 फरवरी 2021, 18:48