見出し画像

レイアウト機能


layoutsフォルダに作成しタグで囲む

デフォルトで適用するにはdefault.vue

デフォルト以外を使用する場合

definePageMeta()を使用する

app.vue

<script setup lang="ts">
//型定義をインポートするときは import type
import type {Character} from "@/interfaces";

const SITE_TITLE = "ワンピース";

//キャラクターリストデータ。
useState<Map<number, Character>>(
  "characterList", //ステート名
  (): Map<number, Character> => { //初期値を生成
    const characterListInit = new Map<number, Character>();
    characterListInit.set(1, {id: 1, name: "ルフィ", bounty: 100000000});
    characterListInit.set(2, {id: 2, name: "ゾロ", bounty: 60000000});
    return characterListInit;
  }
);//characterListでデータの取り出しが可
</script>

<template>
  <NuxtLayout>
    <NuxtPage/>
  </NuxtLayout>
</template>

<style>
main {
  border: black 5px solid;
  padding: 10px;
}
#breadcrumbs ul li {
  display: inline;
  list-style-type: none;
}
#breadcrumbs ul {
  padding-left: 0px;
}
#breadcrumbs ul li:before {
  content: " > ";
}
#breadcrumbs ul li:first-child:before {
  content: none;
}
</style>

layouts/default.vue

<template>
  <header>
    <h1>ワンピース!</h1>
  </header>
  <main>
    <slot/>
  </main>
</template>

layouts/character.vue

<template>
  <header>
    <h1>ワンピース!</h1>
  </header>
  <main>
    <h1>キャラクター設定</h1>
    <slot/>
  </main>
</template>

pages/character/characterList.vue

<script setup lang="ts">
import type {character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <p>
      追加は<NuxtLink v-bind:to="{name: 'character-characterAdd'}">こちら</NuxtLink>から
    </p>
    <section>
      <ul>
        <li
          v-for="[id, character] in characterList"
          v-bind:key="id">
          <NuxtLink v-bind:to="{name: 'character-characterDetail-id', params: {id: id}}">
            No:{{id}} {{character.name}}
          </NuxtLink>
        </li>
      </ul>
    </section>
  </section>
</template>

pages/character/characterAdd.vue

<script setup lang="ts">
import type {character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

//ルータオブジェクトを取得。
const router = useRouter();
// router.push() => 指定の居場所へ
// router.back() => 履歴上で1つ前の画面

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
//入力データと同期させるCharacterオブジェクトの用意。
const character: Character = reactive(
  {
    id: 3,
    name: "",
    bounty: 0,
  }
);
//登録ボタンが押された時の処理。
const onAdd = (): void => {
  characterList.value.set(character.id, character);
  router.push({name: "character-characterList"});
};
</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li><NuxtLink v-bind:to="{name: 'character-characterList'}">キャラクターリスト</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <p>
      情報を入力し、登録ボタンをクリックしてください。
    </p>
    <form v-on:submit.prevent="onAdd">
      <table>
        <tr>
          <td>
            <label for="addId">No:</label>
          </td>
          <td>
            <input type="number" id="addId" v-model.number="character.id" required>
          </td>
        </tr>
        <tr>
          <td>
            <label for="addName">名前:</label>
          </td>
          <td>
            <input type="text" id="addName" v-model="character.name" required>
          </td>
        </tr>
        <tr>
          <td>
            <label for="addBounty">懸賞金:</label>
          </td>
          <td>
            <input type="number" id="addBounty" v-model.number="character.bounty" required>
          </td>
        </tr>
      </table>
      <br>
      <button type="submit">登録</button>
    </form>
  </section>
</template>

pages/character/characterDetail/[id].vue

<script setup lang="ts">
import type {Character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

//ルートオブジェクト(ルートに関する情報を取得)を取得。
const route = useRoute();
// route.name => character-characterDetail-id
// route.path => /character/characterDetail/1
// route.params => { id: 1 }

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
//キャラクターリストから該当キャラクターを取得。
const character = computed(
  (): Character => {
    const id = Number(route.params.id);
    return characterList.value.get(id) as Character;
  }
);

</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li><NuxtLink v-bind:to="{name: 'character-characterList'}">キャラクターリスト</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <table>
      <tr>
        <td>No:</td>
        <td>{{character.id}}</td>
      </tr>
      <tr>
        <td>名前:</td>
        <td>{{character.name}}</td>
      </tr>
      <tr>
        <td>懸賞金:</td>
        <td>{{character.bounty}}ベリー</td>
      </tr>
    </table>
  </section>
</template>

ヘッダー情報

useHead()

プロパティに設定したい情報を渡す

titleTemplate

titleのテンプレート設定できる

app.vue

<script setup lang="ts">
//型定義をインポートするときは import type
import type {Character} from "@/interfaces";

const SITE_TITLE = "ワンピース";

useHead({
  //title: SITE_TITLE
  titleTemplate: (titleChunk: string|undefined): string => {
    return titleChunk != undefined ? `${titleChunk} | ${SITE_TITLE}` : SITE_TITLE; 
  }
});

//キャラクターリストデータ。
useState<Map<number, Character>>(
  "characterList", //ステート名
  (): Map<number, Character> => { //初期値を生成
    const characterListInit = new Map<number, Character>();
    characterListInit.set(1, {id: 1, name: "ルフィ", bounty: 100000000});
    characterListInit.set(2, {id: 2, name: "ゾロ", bounty: 60000000});
    return characterListInit;
  }
);//characterListでデータの取り出しが可
</script>

<template>
  <NuxtLayout>
    <NuxtPage/>
  </NuxtLayout>
</template>

<style>
main {
  border: black 5px solid;
  padding: 10px;
}
#breadcrumbs ul li {
  display: inline;
  list-style-type: none;
}
#breadcrumbs ul {
  padding-left: 0px;
}
#breadcrumbs ul li:before {
  content: " > ";
}
#breadcrumbs ul li:first-child:before {
  content: none;
}
</style>

pages/character/characterList.vue

<script setup lang="ts">
import type {character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

const PAGE_TITLE = "キャラクターリスト";

useHead({
  title: PAGE_TITLE,
});

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <p>
      追加は<NuxtLink v-bind:to="{name: 'character-characterAdd'}">こちら</NuxtLink>から
    </p>
    <section>
      <ul>
        <li
          v-for="[id, character] in characterList"
          v-bind:key="id">
          <NuxtLink v-bind:to="{name: 'character-characterDetail-id', params: {id: id}}">
            No:{{id}} {{character.name}}
          </NuxtLink>
        </li>
      </ul>
    </section>
  </section>
</template>

pages/character/characterAdd.vue

<script setup lang="ts">
import type {character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

const PAGE_TITLE = "キャラクター追加";

useHead({
  title: PAGE_TITLE,
});

//ルータオブジェクトを取得。
const router = useRouter();
// router.push() => 指定の居場所へ
// router.back() => 履歴上で1つ前の画面

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
//入力データと同期させるCharacterオブジェクトの用意。
const character: Character = reactive(
  {
    id: 3,
    name: "",
    bounty: 0,
  }
);
//登録ボタンが押された時の処理。
const onAdd = (): void => {
  characterList.value.set(character.id, character);
  router.push({name: "character-characterList"});
};
</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li><NuxtLink v-bind:to="{name: 'character-characterList'}">キャラクターリスト</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <p>
      情報を入力し、登録ボタンをクリックしてください。
    </p>
    <form v-on:submit.prevent="onAdd">
      <table>
        <tr>
          <td>
            <label for="addId">No:</label>
          </td>
          <td>
            <input type="number" id="addId" v-model.number="character.id" required>
          </td>
        </tr>
        <tr>
          <td>
            <label for="addName">名前:</label>
          </td>
          <td>
            <input type="text" id="addName" v-model="character.name" required>
          </td>
        </tr>
        <tr>
          <td>
            <label for="addBounty">懸賞金:</label>
          </td>
          <td>
            <input type="number" id="addBounty" v-model.number="character.bounty" required>
          </td>
        </tr>
      </table>
      <br>
      <button type="submit">登録</button>
    </form>
  </section>
</template>

pages/character/characterDetail/[id].vue

<script setup lang="ts">
import type {Character} from "@/interfaces";

definePageMeta({
  layout: "character"
});

const PAGE_TITLE = "キャラクター詳細情報";

useHead({
  title: PAGE_TITLE,
});

//ルートオブジェクト(ルートに関する情報を取得)を取得。
const route = useRoute();
// route.name => character-characterDetail-id
// route.path => /character/characterDetail/1
// route.params => { id: 1 }

//キャラクターリストをステートから取得。
const characterList = useState<Map<number, Character>>("characterList");
//キャラクターリストから該当キャラクターを取得。
const character = computed(
  (): Character => {
    const id = Number(route.params.id);
    return characterList.value.get(id) as Character;
  }
);

</script>

<template>
  <nav id="breadcrumbs">
    <ul>
      <li><NuxtLink v-bind:to="{name: 'index'}">TOP</NuxtLink></li>
      <li><NuxtLink v-bind:to="{name: 'character-characterList'}">キャラクターリスト</NuxtLink></li>
      <li>{{PAGE_TITLE}}</li>
    </ul>
  </nav>
  <section>
    <h2>{{PAGE_TITLE}}</h2>
    <table>
      <tr>
        <td>No:</td>
        <td>{{character.id}}</td>
      </tr>
      <tr>
        <td>名前:</td>
        <td>{{character.name}}</td>
      </tr>
      <tr>
        <td>懸賞金:</td>
        <td>{{character.bounty}}ベリー</td>
      </tr>
    </table>
  </section>
</template>


この記事が気に入ったらサポートをしてみませんか?