JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<h2>Todo:</h2>
<ol class="tasks">
<task-element
v-for="(n, i) in todos"
:key="n.id"
:task="n"
@update="Object.assign(n, $event)"
@delete="todos.splice(i, 1)"
></task-element>
</ol>
<h3>Add new task:</h3>
<input placeholder="New Todo" v-model="newTodo" @keypress.enter="addTodo">
<button type="button" @click="addTodo">Add task</button>
</div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: monospace;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
width: 250px;
border-bottom: 1px solid #ccc;
margin-bottom: 20px;
}
label.islong span::before {
content: "⌛";
}
div.loaded ol.tasks li span {
opacity: 1;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.created {
color: #999;
}
JavaScript
Vue.component('task-element', {
props: [ 'task' ],
data: () => ({
created: null,
}),
template : `
<li>
<label :class="{ islong: task.text.length >= 15 }">
<input type="checkbox" v-model="done">
<span v-text="task.text"></span>
</label>
<button v-if="task.done" @click="$emit('delete')">delete</button>
<div
v-if="created !== null"
v-text="\`created \${created} seconds ago\`"
class="created"
></div>
</li>`,
computed: {
done: {
get() {
return this.task.done;
},
set(done) {
this.$emit('update', { done });
},
},
},
created() {
const { createdAt } = this.task;
if (createdAt) {
const updateCreated = () => this.created = Math.floor((Date.now() - createdAt) / 1000);
const interval = setInterval(updateCreated, 1000);
this.$on('hook:beforeDestroy', () => clearInterval(interval));
updateCreated();
}
},
});
new Vue({
el: '#app',
data: () => ({
newTodo: '',
todos: [
{ id: 1, text: 'Task 1', done: false },
{ id: 2, text: 'Task 2', done: false, createdAt: Date.now() - 15000 },
{ id: 3, text: 'Task 3', done: true },
],
}),
methods: {
addTodo() {
const text = this.newTodo;
if (text.length) {
this.todos.push({
id: 1 + Math.max(0, ...this.todos.map(n => n.id)),
text,
done: false,
createdAt: Date.now(),
});
this.newTodo = '';
} else {
alert('empty');
}
},
},
});