Vue
by tawowohzyk
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.5.1/vuex.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css">
<div id="app">
<ul class="nav nav-tabs justify-content-end">
<li class="nav-item" v-for="(group) in groups" :key="group.id">
<a class="nav-link active" href="#" @click="activateGroup(group)" v-if="group.id == activeGroupId">
{{ group.name }} ({{ curMessagesCount }})
</a>
<a class="nav-link" href="#" @click="activateGroup(group)" v-else>
{{ group.name }}
</a>
</li>
</ul>
<table class="table table-bordered">
<thead>
<tr>
<th>講話的人</th>
<th>訊息</th>
</tr>
</thead>
<tbody>
<tr v-for="msg in curMessages" :key="msg.id">
<td>{{ msg.sent_by }}</td>
<td>{{ msg.content }}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<form class="form-inline">
<label class="sr-only" for="inlineFormInputName2">Name</label>
<input type="text" class="form-control mb-2 mr-sm-2" placeholder="..." v-model="newMessage">
<button type="submit" class="btn btn-primary mb-2" @click.prevent="sendMessage">Submit</button>
</form>
</td>
</tr>
</tfoot>
</table>
</div>
Vue
const MessageStore = {
namespaced: true,
// 因為這個 MessageStore 會被重複使用,
// 透過這種寫法才能讓各個 MessageStore instance 的 state 互相獨立
// https://vuex.vuejs.org/zh/guide/modules.html#%E6%A8%A1%E5%9D%97%E9%87%8D%E7%94%A8
state: () => ({
messages: []
}),
getters: {
messagesCount (state) {
return state.messages.length;
}
},
// 必須搭配 namespaced:true 這個設定,
// 否則mutations, actions, getters 都會被註冊在全域
mutations: {
addMessage(state, { sent_by, content }) {
state.messages.push({
sent_by,
content,
id: (new Date).getTime()
});
}
}
};
// 用 root store 來管理群組
// 在動態加入的同時,順便動態註冊MessageStore
const store = new Vuex.Store({
state: {
groups: [],
added: 0,
activeGroupId: null
},
mutations: {
addGroup (state, group) {
state.groups.push(group);
state.added++;
},
activateGroup (state, { id }) {
state.activeGroupId = id;
},
// 這種動態註冊 module 的 function 也可以寫在 vue component,
// 寫在這邊單純是想給需要的人示範在mutation裡面做...
initMessageStore (state, { id }) {
// 這邊的 this 指向 root store
const exists = this.hasModule(['groupMessages', id]);
if (! exists) {
this.registerModule(['groupMessages', id], MessageStore);
}
},
},
getters: {
// 用現在開啟的groupId找到動態store的state
curMessages(state) {
return state.activeGroupId
? state.groupMessages[state.activeGroupId].messages
: [];
},
curMessagesCount(state, getters) {
return state.activeGroupId
? getters[`groupMessages/${state.activeGroupId}/messagesCount`]
: 0;
}
},
modules: {
// 如果要直接宣告nested module,要確保每一層module都存在,在這邊我就直接宣告了
// 可以拿掉試試看,會出現『parent is undefined』的訊息唷
groupMessages: {
// 你可能會覺得 MessageStore 那邊就有 namespaced:true 的設定了,這邊是不是多餘的?
// 其實不是
// 如果拿掉,會出現『[vuex] unknown mutation type: groupMessages/1/addMessage』的錯誤喔
namespaced: true
}
},
});
new Vue({
el: "#app",
data: () => {
...