在前面的單元,我們已經完成了開發單一元件Task,也完成了複合元件 TaskList,也把 TaskList 拆分為容器型(TaskList.vue) 及 表現型(PureTaskList.vue),接下來要做的是把元件組合成頁面 - InboxScreen。
元件驅動開發 Component-Driven Development(CDD),是指從元件開始向上開發,逐步的擴充及組合元件,到最後完成一個頁面。
在 InboxScreen 除了使用 TaskList,也會在當頁面出問題時呈現錯誤的樣式。InboxScreen 也會拆分成容器型(InboxScreen.vue) 及表現型 (PureInboxScreen.vue)
表現型會做DOM markup及樣式呈現,如果有 error 就顯示錯誤區塊,否則就呈現 TaskList
<!--src/components/PureInboxScreen.vue-->
<template>
<div>
<div class="page lists-show" v-if="error">
<div class="wrapper-message">
<span class="icon-face-sad" />
<div class="title-message">Oh no!</div>
<div class="subtitle-message">Something went wrong</div>
</div>
</div>
<div class="page lists-show" v-else>
<nav>
<h1 class="title-page">
<span class="title-wrapper">Taskbox</span>
</h1>
</nav>
<task-list />
</div>
</div>
</template>
<script>
import TaskList from './TaskList.vue';
export default {
name: 'pure-inbox-screen',
props: {
error: {
type: Boolean,
default: false,
},
},
components: {
TaskList,
},
};
</script>
容器型會做資料及狀態管理,把內容利用props傳給表現型
<!--src/components/InboxScreen.vue-->
<template>
<div>
<pure-inbox-screen :error="error" />
</div>
</template>
<script>
import PureInboxScreen from './PureInboxScreen';
import { mapState } from 'vuex';
export default {
name: 'inbox-screen',
components: {
PureInboxScreen,
},
computed: {
...mapState(['error']),
},
};
</script>
App.vue 使用 InboxScreen.vue (容器型)
<!--src/App.vue-->
<template>
<div id="app">
<inbox-screen />
</div>
</template>
<script>
import store from './store';
import InboxScreen from './components/InboxScreen.vue';
export default {
name: 'app',
store,
components: {
InboxScreen,
},
};
</script>
<style>
@import "./assets/index.css";
</style>
//src/components/PureInboxScreen.stories.js
import PureInboxScreen from './PureInboxScreen.vue';
export default {
title: 'PureInboxScreen',
};
// inbox screen default state
export const Default = () => ({
components: { PureInboxScreen },
template: `<pure-inbox-screen/>`,
});
// inbox screen error state
export const error = () => ({
components: { PureInboxScreen },
template: `<pure-inbox-screen :error="true"/>`,
});
現在Storybook有出現PureInboxScreen的元件清單,但Default Story,還需要把內容傳給它做呈現
//src/components/PureInboxScreen.stories.js
import Vue from 'vue';
import Vuex from 'vuex';
import PureInboxScreen from './PureInboxScreen.vue';
import { action } from '@storybook/addon-actions';
import { defaultTasksData } from './PureTaskList.stories';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
tasks: defaultTasksData,
},
actions: {
pinTask(context, id) {
action('pinTask')(id);
},
archiveTask(context, id) {
action('archiveTask')(id);
},
},
});
export default {
title: 'PureInboxScreen',
excludeStories: /.*store$/,
};
export const Default = () => ({
components: { PureInboxScreen },
template: `<pure-inbox-screen/>`,
store,
});
// tasklist with pinned tasks
export const error = () => ({
components: { PureInboxScreen },
template: `<pure-inbox-screen :error="true"/>`,
});
本篇修改的程式碼:https://git.io/JUySW
接下來的二個單元就介紹 Angular 元件 CDD 搭配 ngrx 的寫法。
Construct a screen - Vue