上QQ阅读APP看书,第一时间看更新
2.2.1 运行整个项目
新建文件内容如下:
<!DOCTYPE html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" type="text/css" href="https://unpkg.com/todomvc-app- css@2.2.0/index.css"> <script src="https://cdn.jsdelivr.net/npm/vue@3.2.2"></script> <script type="text/javascript"> window.onload=function(){ var STORAGE_KEY = 'todos-vuejs' var todoStorage = { fetch: function () { var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]') todos.forEach(function (todo, index) { todo.id = index }) todoStorage.uid = todos.length return todos }, save: function (todos) { localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)) } } // 过滤器,用来根据条件过滤 var filters = { all: function (todos) { return todos }, active: function (todos) { return todos.filter(function (todo) { return !todo.completed }) }, completed: function (todos) { return todos.filter(function (todo) { return todo.completed }) } } // 创建Vue的实例(instance) var app = Vue.createApp({ // 设置页面用到的各种变量 data() { return { todos: todoStorage.fetch(), newTodo: '', editedTodo: null, visibility: 'all' } }, // 监听变量的修改 watch: { todos: { handler: function (todos) { todoStorage.save(todos) }, deep: true } }, // 计算函数 computed: { filteredTodos: function () { return filters[this.visibility](this.todos) }, remaining: function () { return filters.active(this.todos).length }, allDone: { get: function () { return this.remaining === 0 }, set: function (value) { this.todos.forEach(function (todo) { todo.completed = value }) } } }, // 定义各种方法 methods: { addTodo: function () { var value = this.newTodo && this.newTodo.trim() if (!value) { return } this.todos.push({ id: todoStorage.uid++, title: value, completed: false }) this.newTodo = '' }, removeTodo: function (todo) { this.todos.splice(this.todos.indexOf(todo), 1) }, editTodo: function (todo) { this.beforeEditCache = todo.title this.editedTodo = todo }, doneEdit: function (todo) { if (!this.editedTodo) { return } this.editedTodo = null todo.title = todo.title.trim() if (!todo.title) { this.removeTodo(todo) } }, cancelEdit: function (todo) { this.editedTodo = null todo.title = this.beforeEditCache }, }, directives: { 'todo-focus': function (el, binding) { if (binding.value) { el.focus() } } } }) app.mount('.todoapp') } </script> </head> <body> <section class="todoapp"> <header class="header"> <h1>待办事项</h1> <input class="new-todo" autofocus autocomplete="off" placeholder="例如:背10个单词.回车保存, 双击编辑" v-model="newTodo" @keyup.enter="addTodo"> </header> <section class="main" v-show="todos.length" v-cloak> <input class="toggle-all" type="checkbox" v-model="allDone"> <ul class="todo-list"> <li v-for="todo in filteredTodos" class="todo" :key="todo.id" :class="{ completed: todo.completed, editing: todo == editedTodo }"> <div class="view"> <input class="toggle" type="checkbox" v-model="todo.completed"> <label @dblclick="editTodo(todo)">{{ todo.title }}</label> <button class="destroy" @click="removeTodo(todo)"></button> </div> <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> </li> </ul> </section> <footer class="footer" v-show="todos.length" v-cloak> <span class="todo-count"> <strong>{{ remaining }}</strong> left </span> </footer> </section> </body> </html>
将该文件保存后,使用浏览器直接打开,就可以看到效果。原生Vue.js的TODO-list项目界面如图2-2所示。
图2-2 原生Vue.js的TODO-list项目界面