Phoenix LiveView를 사용하여 간단한 캘린더 클론 구축(섹션 3)

26181 단어 liveviewelixirphoenix
이 시리즈의 마지막 부분에서 우리는 새로운 Phoenix 프로젝트를 만들고 Tailwind CSS를 지원하기 위해 필요한 변경을 진행했다.이벤트 형식과 이벤트로 구성된 역 모델을 정의하여 이들의 이동 파일과 외부 모델을 생성합니다.마지막으로, 우리는seeds 파일을 사용하여 세 가지 이벤트 형식으로 데이터베이스를 채웁니다.이 부분에서 우리는 응용 프로그램의 공공 부분을 구축하기 시작할 것이다. 방문객들은 그 중에서 하나, 날짜와 시작 시간을 선택하여 우리와 함께 활동을 안배할 것이다.더 정확히 말하면 이벤트 유형 선택 페이지를 살펴보고 두 가지 새로운 LiveView 기능을 활용합니다.

  • 현장 회의.

  • 기능 구성 요소.
  • 우리 시작합시다!

    그 전에 LiveView가 어떻게 작동하는지 살펴보겠습니다.


    LiveView 및 작동 방식에 익숙해진 경우 이 부분을 건너뛰고 다음 섹션으로 이동할 수 있습니다.그렇지 않으면 LiveView의 내부 작동 방식을 이해하는 것이 코드를 작성하는 데 도움이 될 수 있으므로 계속하기 전에 이 섹션을 읽어 보십시오.모든 LiveView는 일반 HTTP 요청과 표준 HTML 응답으로 시작합니다.처음에 HTML 응답이 브라우저에 나타나면 LiveView의 JS 클라이언트가 페이지와 응용 프로그램 사이에 Phoenix 소켓 연결을 엽니다.이 플러그인 연결은 상태를 저장하고 메시지를 받아서 상태를 업데이트하는 프로세스에 불과하다.LiveView는 내부 상태(할당이라고도 함)가 변경될 때마다 HTML 관련 부분을 다시 제출하고 플러그인을 통해 변화를 브라우저로 되돌려주며 JS 클라이언트는 브라우저에서 DOM에 효과적으로 변화를 적용합니다.가장 주의해야 할 것은 자바스크립트가 활성화되었든 안 되었든 LiveView는 첫 번째 HTML 응답을 보장할 수 있기 때문에 색인, SEO 등에 매우 편리하다.

    공중 현장 회의


    Live session는 LiveView의 새로운 기능 중 하나입니다.이것은 서버에 추가 HTTP 요청을 하지 않고 소켓을 통해 그들 사이의 내비게이션을 처리할 수 있는 실시간 루트를 정의한다.동일한 루트 레이아웃과 LiveViewmount 라이프 사이클에 첨부할 갈고리 목록을 공유할 수 있습니다.실시간 보기에서 플러그인에 같은 데이터를 반복해서 분배해야 할 때 매우 편리합니다.우리의 예에서, 달력의 소유자로서, 우리는 방문자에게 우리의 이름을 보여 주기를 희망한다.애플리케이션 구성에 추가합니다.
    # ./config/config.exs
    
    import Config
    
    config :calendlex,
      # ...
      owner: %{
        name: "Bigardone"
      }
    
    # ...
    
    이제 라우터 파일에서 실시간 세션:public을 만듭니다.
    # ./lib/calendlex_web/router.ex
    
    defmodule CalendlexWeb.Router do
      use CalendlexWeb, :router
    
      # ...
    
      live_session :public, on_mount: CalendlexWeb.Live.InitAssigns do
        scope "/", CalendlexWeb do
          pipe_through :browser
    
          live "/", PageLive
        end
      end
    end
    
    :owner 구성을 :public 실시간 세션의 모든 실시간 보기에 대한 소켓에 지정하려면 :on_mount 옵션에 지정된 새 모듈을 사용합니다.이 제품을 만들려면 다음과 같이 하십시오.
    # ./lib/calendlex_web/live/init_assigns.ex
    
    defmodule CalendlexWeb.Live.InitAssigns do
      import Phoenix.LiveView
    
      def on_mount(:default, _params, _session, socket) do
        owner = Application.get_env(:calendlex, :owner)
        socket = assign(socket, :owner, owner)
    
        {:cont, socket}
      end
    end
    
    실시간 세션 갈고리는 on_mount 리셋을 실현해야 한다. 갈고리의 표지부 (여러 버전을 정의할 때 패턴 일치), 공공 매개 변수, 세션, 플러그인을 수신해야 한다.프로그램의 설정에서 소유자의 데이터를 가져와 플러그인에 분배한 다음 {:cont, socket} 되돌아와서 LiveView의 흐름을 계속합니다.공공 세션의 모든 실시간 보기에는 소유자의 데이터가 있습니다. 우리는 우리의 첫 번째 실시간 보기를 계속하고 실현할 수 있습니다.

    이벤트 유형 선택 페이지


    이 페이지는 프로그램의 루트 경로에 표시됩니다. 모든 사용 가능한 이벤트 형식을 보여 줍니다. 사용자가 하나를 선택하면 다음 페이지로 리셋할 수 있습니다.

    이전 섹션에서 생성된 PageLive 모듈 편집을 시작합니다.
    # ./lib/calendlex_web/live/page_live.ex
    
    defmodule CalendlexWeb.PageLive do
      use CalendlexWeb, :live_view
    
      # We will implement this module in a minute...
      alias CalendlexWeb.Components.EventType
    
      def mount(_params, _session, socket) do
        event_types = Calendlex.available_event_types()
    
        {:ok, assign(socket, event_types: event_types), temporary_assigns: [event_types: []]}
      end
    end
    
    LiveView를 보일 때 mount/3 리셋을 호출하고,private session 와 일부public params 를 받아들인다.이 리셋에서 우리는 보여주고 싶은 필요한 데이터를 얻을 수 있다.따라서 데이터베이스에서 사용할 수 있는 모든 이벤트 형식을 가져와 템플릿에 표시할 수 있도록 플러그인에 할당합니다.템플릿이 나타나면 temporary_assigns 값을 빈 목록으로 설정해서 큰 목록 항목이 있을 때 메모리 문제를 방지합니다.event_types 아직 존재하지 않으므로 계속 구현해 보겠습니다.
    # ./lib/calendlex.ex
    
    defmodule Calendlex do
      defdelegate available_event_types, to: Calendlex.EventType.Repo, as: :available
    end
    
    우리는 Calendlex.available_event_types/0 모듈을 CalendlexCalendlexWeb.* 명명 공간 사이의 공공 인터페이스로 사용할 것이다.이렇게 하면 층 또는 Calendlex.*는 세부 사항이나 업무 논리나 CalenlexWeb.*를 실현하는 내부 구조를 알 필요가 없다.이 모듈은 이벤트 유형과 관련된 모든 CRUD 작업을 수행하는 적절한 내부 모듈Calendlex.*에 의뢰하는 available_event_types/0 기능을 공개했다.이 모듈을 계속 만들겠습니다.
    # ./lib/calendlex/event_type/repo.ex
    
    defmodule Calendlex.EventType.Repo do
      alias Calendlex.{EventType, Repo}
      import Ecto.Query, only: [order_by: 3]
    
      def available do
        EventType
        |> order_by([e], e.name)
        |> Repo.all()
      end
    end
    
    사용 가능한 함수는 매우 간단하다.이것은 데이터베이스에서 Calendlex.EventType.Repo 순서대로 정렬된 모든 이벤트 형식을 가져옵니다.name 실시간 보기에서 우리는 두 가지 다른 옵션을 가지고 그것들을 과장한다.하나는 같은 LiveView 모듈에서 PageLive 리셋 함수를 실현하는 것이고, 다른 하나는 우리가 이전 부분에서 했던 것처럼 새로운 템플릿 파일을 만드는 것이다.저는 보통 두 번째 옵션을 더 좋아하기 때문에 템플릿 파일을 계속 수정하도록 하겠습니다.
    # ./lib/calendlex_web/live/page_live.html.heex
    
    <section class="w-1/2 mx-auto">
      <div class="p-6 mb-2 bg-white border border-gray-200 shadow-md rounded-md">
        <header class="w-2/5 mx-auto mb-12 text-center">
          <h1 class="mb-5 text-xl font-semibold text-gray-500"><%= @owner.name %></h1>
          <p class="text-gray-500">Welcome to my scheduling page. Please follow the instructions to add an event to my calendar.</p>
        </header>
        <div class="mt-4 grid grid-cols-2 gap-x-6">
          <%= for event_type <- @event_types do %>
            <EventType.selector event_type={event_type} path={Routes.live_path(@socket, CalendlexWeb.EventTypeLive, event_type.slug)} />
          <% end %>
        </div>
      </div>
    </section>
    
    우리는 이전에 render/1 갈고리에 분배된 소유자 명칭값<%= @owner.name %>을 가리킨다.사용 가능한 이벤트 형식을 보여주기 위해, 플러그인에 분배된 CalendlexWeb.Live.InitAssigns.on_mount/4 목록을 훑어보았고, 함수 구성 요소인 LiveView에 추가된 새로운 기능을 호출했습니다.LiveView 0.16에 새로운 element_types HTML 엔진이 도입되었기 때문에, 우리는 현재 일반적인 HTML 표시를 사용하여 이 구성 요소들을 호출할 수 있습니다. 이것은 매우 편리해서, 나로 하여금 React를 떠올리게 합니다.

    EventType 선택기 함수 구성 요소


    Function components 또는 무상태 구성 요소는 일반 함수이며 HEEx 매개 변수를 받고 assigns sigil과 보여줄 HTML을 되돌려야 합니다.그것들은 어떤 메시지도 처리할 수 없고 내부 상태도 저장할 수 없다.구성 요소의 모듈을 만듭니다.
    # ./lib/calendlex_web/live/components/event_type.ex
    
    defmodule CalendlexWeb.Components.EventType do
      use Phoenix.Component
    
      def selector(assigns) do
        ~H"""
        <%= live_redirect to: @path do %>
          <div class="flex items-center p-6 pb-20 text-gray-400 bg-white border-t border-gray-300 cursor-pointer hover:bg-gray-200 gap-x-4">
            <div {[class: "inline-block w-8 h-8 #{@event_type.color}-bg rounded-full border-2 border-white"]}></div>
            <h3 class="font-bold text-gray-900"><%= @event_type.name %></h3>
            <div class="ml-auto text-xl"><i class="fas fa-caret-right"></i></div>
          </div>
        <% end %>
        """
      end
    end
    
    ~H 템플릿에서 EventType.event_type, 설정PageLiveevent_type 속성을 호출하고 있기 때문에 이 값들은 자동으로 분배되어 pathsigil에서 사용할 수 있습니다.
    터미널을 확인하면 값이 존재하지 않는 활성 경로 값에 해당하는 ~H 값으로 인해 다음과 같은 오류가 발생합니다.
    [error] #PID<0.564.0> running CalendlexWeb.Endpoint (connection #PID<0.555.0>, stream id 4) terminated
    Server: localhost:4000 (http)
    Request: GET /
    ** (exit) an exception was raised:
        ** (ArgumentError) no action CalendlexWeb.EventTypeLive for CalendlexWeb.Router.Helpers.live_path/3. The following actions/clauses are supported:
    
        live_path(conn_or_endpoint, CalendlexWeb.PageLive, params \\ [])
    
    오류를 수정하기 위해 라우터에 적절한 실시간 경로를 추가합니다.
    # ./lib/calendlex_web/router.ex
    
    defmodule CalendlexWeb.Router do
      use CalendlexWeb, :router
    
      # ...
    
      live_session :public, on_mount: CalendlexWeb.Live.InitAssigns do
        scope "/", CalendlexWeb do
          # ...
    
          live "/:event_type_slug", EventTypeLive
        end
      end
    
    마지막으로 적절한 빈 LiveView 모듈과 템플릿을 추가합니다.
    # ./lib/calendlex_web/live/event_type_live.ex
    
    defmodule CalendlexWeb.EventTypeLive do
      use CalendlexWeb, :live_view
    
      def mount(%{"event_type_slug" => _slug} = params, _session, socket) do
        {:ok, socket}
      end
    end
    
    <!-- ./lib/calendlex_web/live/event_type_live.html.heex -->
    
    <h1>EventTypeLive</h1>
    
    브라우저로 다시 이동하려면 다음과 같이 하십시오.

    레이아웃과 스타일을 마지막으로 윤색하려면 main CSS file의 내용을 복사하여 로컬 버전에 붙여넣은 다음 루트 레이아웃과 실시간 레이아웃의 내용을 다음과 같이 바꿉니다.
    <!-- ./lib/calendlex_web/templates/layout/root.html.heex -->
    
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <%= csrf_meta_tag() %>
        <%= live_title_tag assigns[:page_title] || assigns[:owner][:name], suffix: " · Calendlex" %>
        <link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
        <script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
        <script src="https://kit.fontawesome.com/9539f8cd16.js" crossorigin="anonymous"></script>
      </head>
      <body class="antialiased text-gray-600 bg-gray-100">
        <div class="flex flex-col h-screen">
          <%= @inner_content %>
        </div>
      </body>
    </html>
    
    <!-- ./lib/calendlex_web/templates/layout/live.html.heex -->
    
    <main role="main" class="flex-1 pt-20">
      <p class="alert alert-info" role="alert"
        phx-click="lv:clear-flash"
        phx-value-key="info"><%= live_flash(@flash, :info) %></p>
    
      <p class="alert alert-danger" role="alert"
        phx-click="lv:clear-flash"
        phx-value-key="error"><%= live_flash(@flash, :error) %></p>
    
      <%= @inner_content %>
    </main>
    
    브라우저가 페이지를 새로 고치면 모든 것이 더 좋아 보일 것이다.

    오늘은 여기까지.다음 섹션에서는 이벤트타입 라이브 뷰를 처리하여 달력을 보여줍니다. 달력에서 방문객은 날짜와 여가 시간을 선택하여 저희와 함께 행사를 마련할 수 있습니다.LiveView의 다양한 기능(예: 실시간 구성 요소 및 현재 탐색 패치)을 활용합니다.또한 live demo에서 최종 결과를 보거나 source code를 볼 수 있습니다.
    즐거운 코딩!

    비카덴 / calendlex


    Phoenix LiveView를 통한 간편한 클론 복제

    좋은 웹페이지 즐겨찾기