mirror of https://github.com/vuejs/core.git
223 lines
7.4 KiB
HTML
223 lines
7.4 KiB
HTML
<script src="../../dist/vue-vapor.global.js"></script>
|
|
<link rel="stylesheet" href="../../../../node_modules/todomvc-app-css/index.css">
|
|
|
|
<div id="app"></div>
|
|
|
|
<script>
|
|
const { createVaporApp, defineComponent, reactive, computed, watchEffect, onMounted, onUnmounted, nextTick } = VueVapor
|
|
|
|
const STORAGE_KEY = 'todos-vuejs-3.x'
|
|
const todoStorage = {
|
|
fetch () {
|
|
const todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
|
|
todos.forEach((todo, index) => {
|
|
todo.id = index
|
|
})
|
|
todoStorage.uid = todos.length
|
|
return todos
|
|
},
|
|
save (todos) {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
|
|
}
|
|
}
|
|
|
|
const filters = {
|
|
all (todos) {
|
|
return todos
|
|
},
|
|
active (todos) {
|
|
return todos.filter((todo) => {
|
|
return !todo.completed
|
|
})
|
|
},
|
|
completed (todos) {
|
|
return todos.filter(function (todo) {
|
|
return todo.completed
|
|
})
|
|
}
|
|
}
|
|
|
|
function pluralize (n) {
|
|
return n === 1 ? 'item' : 'items'
|
|
}
|
|
|
|
const _sfc_main = defineComponent({
|
|
setup() {
|
|
const state = reactive({
|
|
todos: todoStorage.fetch(),
|
|
editedTodo: null,
|
|
newTodo: '',
|
|
beforeEditCache: '',
|
|
visibility: 'all',
|
|
remaining: computed(() => {
|
|
return filters.active(state.todos).length
|
|
}),
|
|
remainingText: computed(() => {
|
|
return ` ${pluralize(state.remaining)} left`
|
|
}),
|
|
filteredTodos: computed(() => {
|
|
return filters[state.visibility](state.todos)
|
|
}),
|
|
allDone: computed({
|
|
get: function () {
|
|
return state.remaining === 0
|
|
},
|
|
set: function (value) {
|
|
state.todos.forEach(todo => {
|
|
todo.completed = value
|
|
})
|
|
},
|
|
}),
|
|
})
|
|
|
|
watchEffect(() => {
|
|
todoStorage.save(state.todos)
|
|
})
|
|
|
|
onMounted(() => {
|
|
window.addEventListener('hashchange', onHashChange)
|
|
onHashChange()
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('hashchange', onHashChange)
|
|
})
|
|
|
|
function onHashChange() {
|
|
const visibility = window.location.hash.replace(/#\/?/, '')
|
|
if (filters[visibility]) {
|
|
state.visibility = visibility
|
|
} else {
|
|
window.location.hash = ''
|
|
state.visibility = 'all'
|
|
}
|
|
}
|
|
|
|
function addTodo() {
|
|
const value = state.newTodo && state.newTodo.trim()
|
|
if (!value) {
|
|
return
|
|
}
|
|
state.todos.push({
|
|
id: todoStorage.uid++,
|
|
title: value,
|
|
completed: false,
|
|
})
|
|
state.newTodo = ''
|
|
}
|
|
|
|
function removeTodo(todo) {
|
|
state.todos.splice(state.todos.indexOf(todo), 1)
|
|
}
|
|
|
|
async function editTodo(todo) {
|
|
state.beforeEditCache = todo.title
|
|
state.editedTodo = todo
|
|
await nextTick()
|
|
document.getElementById(`todo-${todo.id}-input`).focus()
|
|
}
|
|
|
|
function doneEdit(todo) {
|
|
if (!state.editedTodo) {
|
|
return
|
|
}
|
|
state.editedTodo = null
|
|
todo.title = todo.title.trim()
|
|
if (!todo.title) {
|
|
removeTodo(todo)
|
|
}
|
|
}
|
|
|
|
function cancelEdit(todo) {
|
|
state.editedTodo = null
|
|
todo.title = state.beforeEditCache
|
|
}
|
|
|
|
function removeCompleted() {
|
|
state.todos = filters.active(state.todos)
|
|
}
|
|
|
|
return {
|
|
state,
|
|
addTodo,
|
|
removeTodo,
|
|
editTodo,
|
|
doneEdit,
|
|
cancelEdit,
|
|
removeCompleted,
|
|
}
|
|
},
|
|
})
|
|
|
|
const { children: _children, vModelText: _vModelText, withDirectives: _withDirectives, vShow: _vShow, next: _next, delegate: _delegate, on: _on, renderEffect: _renderEffect, setDynamicProp: _setDynamicProp, setText: _setText, setClass: _setClass, createFor: _createFor, insert: _insert, delegateEvents: _delegateEvents, template: _template } = VueVapor
|
|
const t0 = _template("<li><div class=\"view\"><input class=\"toggle\" type=\"checkbox\"><label></label><button class=\"destroy\"></button></div><input class=\"edit\" type=\"text\"></li>")
|
|
const t1 = _template("<section class=\"todoapp\"><header class=\"header\"><h1>todos</h1><input class=\"new-todo\" autofocus autocomplete=\"off\" placeholder=\"What needs to be done?\"></header><section class=\"main\"><input id=\"toggle-all\" class=\"toggle-all\" type=\"checkbox\"><label for=\"toggle-all\">Mark all as complete</label><ul class=\"todo-list\"></ul></section><footer class=\"footer\"><span class=\"todo-count\"><strong></strong><span></span></span><ul class=\"filters\"><li><a href=\"#/all\">All</a></li><li><a href=\"#/active\">Active</a></li><li><a href=\"#/completed\">Completed</a></li></ul><button class=\"clear-completed\"> Clear completed </button></footer></section>")
|
|
_delegateEvents("keyup", "dblclick", "click", "input")
|
|
|
|
function _sfc_render(_ctx) {
|
|
const n18 = t1()
|
|
const n0 = _children(n18, 0, 1)
|
|
_withDirectives(n0, [[_vModelText, () => _ctx.state.newTodo]])
|
|
const n10 = _children(n18, 1)
|
|
_withDirectives(n10, [[_vShow, () => _ctx.state.todos.length]])
|
|
const n1 = n10.firstChild
|
|
const n9 = _next(n1, 2)
|
|
const n17 = n10.nextSibling
|
|
_withDirectives(n17, [[_vShow, () => _ctx.state.todos.length]])
|
|
const n11 = _children(n17, 0, 0)
|
|
const n12 = n11.nextSibling
|
|
const n13 = _children(n17, 1, 0, 0)
|
|
const n14 = _children(n17, 1, 1, 0)
|
|
const n15 = _children(n17, 1, 2, 0)
|
|
const n16 = _children(n17, 2)
|
|
_withDirectives(n16, [[_vShow, () => _ctx.state.todos.length > _ctx.state.remaining]])
|
|
_delegate(n0, "update:modelValue", () => $event => (_ctx.state.newTodo = $event))
|
|
_delegate(n0, "keyup", () => _ctx.addTodo, {
|
|
keys: ["enter"]
|
|
})
|
|
_on(n1, "change", () => $event => (_ctx.state.allDone = $event.target.checked))
|
|
const n2 = _createFor(() => (_ctx.state.filteredTodos), (_ctx2) => {
|
|
const n8 = t0()
|
|
const n4 = _children(n8, 0, 0)
|
|
const n5 = n4.nextSibling
|
|
const n6 = n5.nextSibling
|
|
const n7 = _children(n8, 1)
|
|
_on(n4, "change", () => $event => (_ctx2[0].completed = $event.target.checked))
|
|
_delegate(n5, "dblclick", () => $event => (_ctx.editTodo(_ctx2[0])))
|
|
_delegate(n6, "click", () => $event => (_ctx.removeTodo(_ctx2[0])))
|
|
_delegate(n7, "input", () => $event => (_ctx2[0].title = $event.target.value))
|
|
_on(n7, "blur", () => $event => (_ctx.doneEdit(_ctx2[0])))
|
|
_delegate(n7, "keyup", () => $event => (_ctx.doneEdit(_ctx2[0])), {
|
|
keys: ["enter"]
|
|
})
|
|
_delegate(n7, "keyup", () => $event => (_ctx.cancelEdit(_ctx2[0])), {
|
|
keys: ["escape"]
|
|
})
|
|
_renderEffect(() => _setDynamicProp(n4, "checked", _ctx2[0].completed))
|
|
_renderEffect(() => {
|
|
_setText(n5, _ctx2[0].title)
|
|
_setDynamicProp(n7, "value", _ctx2[0].title)
|
|
})
|
|
_renderEffect(() => _setDynamicProp(n7, "id", `todo-${_ctx2[0].id}-input`))
|
|
_renderEffect(() => _setClass(n8, ["todo", {
|
|
completed: _ctx2[0].completed,
|
|
editing: _ctx2[0] === _ctx.state.editedTodo,
|
|
}]))
|
|
return n8
|
|
}, (todo) => (todo.id))
|
|
_insert(n2, n9)
|
|
_delegate(n16, "click", () => _ctx.removeCompleted)
|
|
_renderEffect(() => _setDynamicProp(n1, "checked", _ctx.state.allDone))
|
|
_renderEffect(() => _setText(n11, _ctx.state.remaining))
|
|
_renderEffect(() => _setText(n12, _ctx.state.remainingText))
|
|
_renderEffect(() => _setClass(n13, { selected: _ctx.state.visibility === 'all' }))
|
|
_renderEffect(() => _setClass(n14, { selected: _ctx.state.visibility === 'active' }))
|
|
_renderEffect(() => _setClass(n15, { selected: _ctx.state.visibility === 'completed' }))
|
|
return n18
|
|
}
|
|
|
|
_sfc_main.render = _sfc_render
|
|
const app = createVaporApp(_sfc_main, {})
|
|
app.mount('#app')
|
|
</script>
|