vue3-core/packages/vue-vapor/examples/composition/todomvc.html

290 lines
8.1 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>