Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【Vue】見た目とロジックを分ける

この記事は、主に下記の記事を参考にしています。
Vueを用いた開発プロジェクト用に「コンポーネント設計・実装ガイドライン」を作った話 - Qiita
Vue使いなら知っておきたいVueのパターン・小技集 - Qiita

ContainerとPresenter

もともとはReactから派生してきた考え方です。
下記記事がわかりやすいです。
[redux] Presentational / Container componentの分離 - react-redux.connect()のつかいかた - Qiita
ComponentとContainerについて - Qiita
Presentational and Container Components - Dan Abramov - Medium

ContainerとPresenterを分けることのメリット

最初はなんでわざわざ分けるのかと不思議でしたが、下記のメリットが大きいのかなと思いました。

同じPresentational Componentに異なる状態ソースを持たせることで、それらを別のContainer Componentsに再利用することができるようになる
ComponentとContainerについて - Qiita より引用

似たようなPresentational Componentが増えてきたらかなり恩恵を受けられるのではないでしょうか。

実装してみる

全体像

  • container がロジック、presenter が UI
  • それぞれのcomponentがに、container, presenterファイルが生成される
  • containerpresenterwrapする
  • componentを呼び出す時は、containerを呼び出す

Container

特徴

・データや振る舞いに責務を持つ
・データや振る舞いをPresentational Componentや他のContainer Componentに提供する
・VuexのstoreやVue Routerのrouteを参照しても良い(しなくても良い)
・通常、DOMのマークアップやCSSスタイルを持たない。(仮にDOMを持つとしても、それはラッパー用のdivタグなど)
Vueを用いた開発プロジェクト用に「コンポーネント設計・実装ガイドライン」を作った話 - Qiita より引用

presenterを読み込む

// presenterの読み込み
// ここでcontainer が presenter を wrap することになる
import SampleModal from './presenter'

// connect 高階関数
const connect = (SampleModal) => {
  return {
    name: `${SampleModal.name}Container`,
    methods: {
      handleLogin(social) {
        this.$auth.loginWith(social)
      }
    },
    render(h) {
      return h(SampleModal, {
        props: {
          // propsとしてmethod, 
          handleLogin: this.handleLogin
        }
      })
    }
  }
}

export default connect(SampleModal)

高階関数 connect

connectが、ContainerとPresenterを結びつけるキーとなっています。
connectは、高階関数で、mapとかと同じですね。
JavaScript 高階関数を説明するよ - Qiita

以下のconnectは、Presentational Componentを引数に取り、そのコンポーネントが関心を持つ、
VuexのmoduleのデータとVue Routerのメソッドへのアクセスを与えたContainer Componentを返す高階関数
Vueを用いた開発プロジェクト用に「コンポーネント設計・実装ガイドライン」を作った話 - Qiita より引用

containrの呼び出し

com@ponentを使用する時は、containerを呼び出して使用します。

import SampleModal from '@/components/common/Sample/container'

Presenter

特徴

  • 見た目に責務を持つ
  • コンポーネント自身の状態はほとんど持たない
  • propsとしてデータとコールバックを受け取れる
  • アクションやストアに依存しない

実装

<script>
export default {
  name: 'SampleModal',
  // props としてuketoru
  props: {
    handleLogin: {
      type: Function,
      default: () => {}
    }
  },
  render(h, context) {
    return (
      <modal
        name="sign-in-modal"
        resizable={true}
        adaptive={true}
        scrollable={true}
        width={this.$device.isMobile ? '90%' : '40%'}
        height="auto"
      >
        <div class="modal-sign-in">
          <p class="modal-sign-in-word">Sign In</p>
          <div class="modal-sign-in-button">
            <button
              class="modal-sign-in-facebook"
              onClick={() => {
                this.handleLogin('facebook')
              }}
            >
              <font-awesome-icon
                icon={['fab', 'facebook']}
                class="modal-sign-in-facebook-font"
              />
              <span class="modal-sign-in-facebook-word">
                Sign In with Facebook
              </span>
            </button>
          </div>
        </div>
      </modal>
    )
  }
}
</script>
// sampleなので、CSSは適当
<style scoped lang="scss">
@import '~assets/scss/variables';
.modal-sign-in {
  padding: 10px;
  .modal-sign-in-word {
    margin: 10px;
  }
  .modal-sign-in-button {
    margin: 5px;
    .modal-sign-in-facebook {
      max-width: 250px;
      .modal-sign-in-facebook-font {
        margin-right: 10px;
      }
      .modal-sign-in-facebook-word {
        font-weight: bold;
      }
    }
  }
}
</style>


その他参考にした記事

export defaultについて - Qiita

sanoyo
自衛隊からソフトウェアエンジニア
https://note.com/yokosano
engineerlife
技術力をベースに人生を謳歌する人たちのコミュニティです。
https://community.camp-fire.jp/projects/view/280040
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away