Skip to content

Commit 4ac217c

Browse files
author
Luke Edwards
committed
feat: useXXX helpers (issue vuejs#1725)
1 parent c3944f3 commit 4ac217c

File tree

19 files changed

+819
-97
lines changed

19 files changed

+819
-97
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const data = require('./mock-data')
2+
const LATENCY = 16
3+
4+
export function getAllMessages (cb) {
5+
setTimeout(() => {
6+
cb(data)
7+
}, LATENCY)
8+
}
9+
10+
export function createMessage ({ text, thread }, cb) {
11+
const timestamp = Date.now()
12+
const id = 'm_' + timestamp
13+
const message = {
14+
id,
15+
text,
16+
timestamp,
17+
threadID: thread.id,
18+
threadName: thread.name,
19+
authorName: 'Evan'
20+
}
21+
setTimeout(function () {
22+
cb(message)
23+
}, LATENCY)
24+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
module.exports = [
2+
{
3+
id: 'm_1',
4+
threadID: 't_1',
5+
threadName: 'Jing and Bill',
6+
authorName: 'Bill',
7+
text: 'Hey Jing, want to give a Flux talk at ForwardJS?',
8+
timestamp: Date.now() - 99999
9+
},
10+
{
11+
id: 'm_2',
12+
threadID: 't_1',
13+
threadName: 'Jing and Bill',
14+
authorName: 'Bill',
15+
text: 'Seems like a pretty cool conference.',
16+
timestamp: Date.now() - 89999
17+
},
18+
{
19+
id: 'm_3',
20+
threadID: 't_1',
21+
threadName: 'Jing and Bill',
22+
authorName: 'Jing',
23+
text: 'Sounds good. Will they be serving dessert?',
24+
timestamp: Date.now() - 79999
25+
},
26+
{
27+
id: 'm_4',
28+
threadID: 't_2',
29+
threadName: 'Dave and Bill',
30+
authorName: 'Bill',
31+
text: 'Hey Dave, want to get a beer after the conference?',
32+
timestamp: Date.now() - 69999
33+
},
34+
{
35+
id: 'm_5',
36+
threadID: 't_2',
37+
threadName: 'Dave and Bill',
38+
authorName: 'Dave',
39+
text: 'Totally! Meet you at the hotel bar.',
40+
timestamp: Date.now() - 59999
41+
},
42+
{
43+
id: 'm_6',
44+
threadID: 't_3',
45+
threadName: 'Functional Heads',
46+
authorName: 'Bill',
47+
text: 'Hey Brian, are you going to be talking about functional stuff?',
48+
timestamp: Date.now() - 49999
49+
},
50+
{
51+
id: 'm_7',
52+
threadID: 't_3',
53+
threadName: 'Bill and Brian',
54+
authorName: 'Brian',
55+
text: 'At ForwardJS? Yeah, of course. See you there!',
56+
timestamp: Date.now() - 39999
57+
}
58+
]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { createApp } from 'vue'
2+
import App from './components/App.vue'
3+
import store from './store'
4+
import { getAllMessages } from './store/actions'
5+
6+
const app = createApp(App)
7+
8+
app.use(store)
9+
10+
app.mount('#app')
11+
12+
getAllMessages(store)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<style src="../css/chat.css"></style>
2+
3+
<template>
4+
<div class="chatapp">
5+
<thread-section></thread-section>
6+
<message-section></message-section>
7+
</div>
8+
</template>
9+
10+
<script>
11+
import ThreadSection from "./ThreadSection.vue";
12+
import MessageSection from "./MessageSection.vue";
13+
14+
export default {
15+
name: "App",
16+
components: {
17+
ThreadSection,
18+
MessageSection,
19+
},
20+
};
21+
</script>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<template>
2+
<li class="message-list-item">
3+
<h5 class="message-author-name">{{ message.authorName }}</h5>
4+
<div class="message-time">
5+
{{ time(message.timestamp) }}
6+
</div>
7+
<div class="message-text">{{ message.text }}</div>
8+
</li>
9+
</template>
10+
11+
<script>
12+
export default {
13+
name: "Message",
14+
props: {
15+
message: Object,
16+
},
17+
setup() {
18+
return {
19+
time: (value) => new Date(value).toLocaleTimeString(),
20+
};
21+
},
22+
};
23+
</script>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<template>
2+
<div class="message-section">
3+
<h3 class="message-thread-heading">{{ thread.name }}</h3>
4+
<ul class="message-list" ref="list">
5+
<message v-for="message in messages" :key="message.id" :message="message">
6+
</message>
7+
</ul>
8+
<textarea
9+
class="message-composer"
10+
v-model="text"
11+
@keyup.enter="sendMessage"
12+
></textarea>
13+
</div>
14+
</template>
15+
16+
<script>
17+
import { ref, watch, nextTick } from "vue";
18+
import { useGetters, useActions } from "vuex";
19+
import Message from "./Message.vue";
20+
21+
export default {
22+
name: "MessageSection",
23+
components: { Message },
24+
setup() {
25+
const list = ref(null);
26+
27+
const text = ref("");
28+
29+
const { thread, messages } = useGetters([
30+
"currentThread",
31+
"sortedMessages",
32+
]);
33+
const { sendMessageAction } = useActions({
34+
sendMessageAction: "sendMessage",
35+
});
36+
37+
watch(
38+
() => thread.value.lastMessage,
39+
() => {
40+
nextTick(() => {
41+
const ul = list.value;
42+
ul.scrollTop = ul.scrollHeight;
43+
});
44+
}
45+
);
46+
47+
function sendMessage() {
48+
const trimedText = text.value.trim();
49+
if (trimedText) {
50+
sendMessageAction(trimedText, thread);
51+
this.text = "";
52+
}
53+
}
54+
55+
return {
56+
list,
57+
text,
58+
thread,
59+
messages,
60+
sendMessage,
61+
};
62+
},
63+
};
64+
</script>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<template>
2+
<li
3+
class="thread-list-item"
4+
:class="{ active }"
5+
@click="$emit('switch-thread', thread.id)">
6+
<h5 class="thread-name">{{ thread.name }}</h5>
7+
<div class="thread-time">
8+
{{ time(thread.lastMessage.timestamp) }}
9+
</div>
10+
<div class="thread-last-message">
11+
{{ thread.lastMessage.text }}
12+
</div>
13+
</li>
14+
</template>
15+
16+
<script>
17+
export default {
18+
name: 'Thread',
19+
props: {
20+
thread: Object,
21+
active: Boolean
22+
},
23+
setup () {
24+
return {
25+
time: value => new Date(value).toLocaleTimeString()
26+
}
27+
}
28+
}
29+
</script>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<template>
2+
<div class="thread-section">
3+
<div class="thread-count">
4+
<span v-show="unreadCount"> Unread threads: {{ unreadCount }} </span>
5+
</div>
6+
<ul class="thread-list">
7+
<thread
8+
v-for="thread in threads"
9+
:key="thread.id"
10+
:thread="thread"
11+
:active="thread.id === currentThread.id"
12+
@switch-thread="switchThread"
13+
>
14+
</thread>
15+
</ul>
16+
</div>
17+
</template>
18+
19+
<script>
20+
import { computed } from "vue";
21+
import { useGetters, useActions } from "vuex";
22+
import Thread from "./Thread.vue";
23+
24+
export default {
25+
name: "ThreadSection",
26+
components: { Thread },
27+
setup() {
28+
return {
29+
...useGetters(["threads", "currentThread", "unreadCount"]),
30+
...useActions(["switchThread"]),
31+
};
32+
},
33+
};
34+
</script>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* This file is provided by Facebook for testing and evaluation purposes
3+
* only. Facebook reserves all rights not expressly granted.
4+
*
5+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
8+
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
9+
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
10+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11+
*/
12+
13+
.chatapp {
14+
font-family: 'Muli', 'Helvetica Neue', helvetica, arial;
15+
max-width: 760px;
16+
margin: 20px auto;
17+
overflow: hidden;
18+
}
19+
20+
.message-list, .thread-list {
21+
border: 1px solid #ccf;
22+
font-size: 16px;
23+
height: 400px;
24+
margin: 0;
25+
overflow-y: auto;
26+
padding: 0;
27+
}
28+
29+
.message-section {
30+
float: right;
31+
width: 65%;
32+
}
33+
34+
.thread-section {
35+
float: left;
36+
width: 32.5%;
37+
}
38+
39+
.message-thread-heading,
40+
.thread-count {
41+
height: 40px;
42+
margin: 0;
43+
}
44+
45+
.message-list-item, .thread-list-item {
46+
list-style: none;
47+
padding: 12px 14px 14px;
48+
}
49+
50+
.thread-list-item {
51+
border-bottom: 1px solid #ccc;
52+
cursor: pointer;
53+
}
54+
55+
.thread-list:hover .thread-list-item:hover {
56+
background-color: #f8f8ff;
57+
}
58+
59+
.thread-list:hover .thread-list-item {
60+
background-color: #fff;
61+
}
62+
63+
.thread-list-item.active,
64+
.thread-list:hover .thread-list-item.active,
65+
.thread-list:hover .thread-list-item.active:hover {
66+
background-color: #efefff;
67+
cursor: default;
68+
}
69+
70+
.message-author-name,
71+
.thread-name {
72+
color: #66c;
73+
float: left;
74+
font-size: 13px;
75+
margin: 0;
76+
}
77+
78+
.message-time, .thread-time {
79+
color: #aad;
80+
float: right;
81+
font-size: 12px;
82+
}
83+
84+
.message-text, .thread-last-message {
85+
clear: both;
86+
font-size: 14px;
87+
padding-top: 10px;
88+
}
89+
90+
.message-composer {
91+
box-sizing: border-box;
92+
font-family: inherit;
93+
font-size: 14px;
94+
height: 5em;
95+
width: 100%;
96+
margin: 20px 0 0;
97+
padding: 10px;
98+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>vuex chat example</title>
6+
<link href="http://fonts.googleapis.com/css?family=Muli" rel="stylesheet" type="text/css">
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
<script src="/__build__/shared.js"></script>
11+
<script src="/__build__/composition/chat.js"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)