A: hi! ~ Hello everyone, I am YK bacteria 🐷, a microsystem front-end ✨, love to think, love to summarize, love to record, love to share 🏹, welcome to follow me 😘 ~ [wechat account: Yk2012Yk2012, wechat public account: ykyk2012]
“This is the 25th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”
Today we will use Vue to do a small demo, to-do list small demo, before using React also did the same function demo, can compare and learn
Project code https://github.com/yk2012/vue_demo/tree/main/demo3_TodoList
1. Target function interface
2. Split interface modules
3. Home page index. HTML
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>vue_demo</title>
</head>
<body>
<div id="app"></div>
<! -- built files will be auto injected -->
</body>
</html>
Copy the code
4. Static page construction
4.1 the main js
- Introduce basic CSS styles
import Vue from 'vue';
import App from './App.vue';
import './base.css';
new Vue({
el: '#app'.components: { App },
template: '<App/>'
})
Copy the code
4.2 App. Vue
<template>
<div class="todo-container">
<div class="todo-wrap">
<TodoHeader />
<TodoList />
<TodoFooter />
</div>
</div>
</template>
<script>
import TodoHeader from './components/TodoHeader';
import TodoList from './components/TodoList';
import TodoFooter from './components/TodoFooter';
export default {
components:{
TodoHeader,
TodoList,
TodoFooter
}
}
</script>
<style>
/*app*/
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
Copy the code
4.3 TodoHeader. Vue
<template>
<div class="todo-header">
<input type="text" placeholder="Please enter your task name and press Enter to confirm."/>
</div>
</template>
<script>
export default{}</script>
<style>
/*header*/
.todo-header input {
width: 560px;
height: 28px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 7px;
}
.todo-header input:focus {
outline: none;
border-color: rgba(82.168.236.0.8);
box-shadow: inset 0 1px 1px rgba(0.0.0.0.075), 0 0 8px rgba(82.168.236.0.6);
}
</style>
Copy the code
4.4 TodoList. Vue
<template>
<ul class="todo-main">
<li>
<label>
<input type="checkbox"/>
<span>xxxxx</span>
</label>
<button class="btn btn-danger" style="display:none">delete</button>
</li>
<li>
<label>
<input type="checkbox"/>
<span>yyyyy</span>
</label>
<button class="btn btn-danger" style="display:none">delete</button>
</li>
</ul>
</template>
<script>
export default{}</script>
<style>
/*main*/
.todo-main {
margin-left: 0px;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40px;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
/*item*/
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
</style>
Copy the code
4.5 TodoFooter. Vue
<template>
<div class="todo-footer">
<label>
<input type="checkbox"/>
</label>
<span>
<span>Completed 0</span>2 / all</span>
<button class="btn btn-danger">Clear completed tasks</button>
</div>
</template>
<script>
export default{}</script>
<style>
/*footer*/
.todo-footer {
height: 40px;
line-height: 40px;
padding-left: 6px;
margin-top: 5px;
}
.todo-footer label {
display: inline-block;
margin-right: 20px;
cursor: pointer;
}
.todo-footer label input {
position: relative;
top: -1px;
vertical-align: middle;
margin-right: 5px;
}
.todo-footer button {
float: right;
margin-top: 5px;
}
</style>
Copy the code
4.6 show
5. Dynamic components
5.1 Dynamically Displaying Initialization Data
App.vue
Define data: array todos {title, complete}
<template>
<div class="todo-container">
<div class="todo-wrap">
<TodoHeader />
<TodoList :todos="todos" />
<TodoFooter />
</div>
</div>
</template>
<script>
import TodoHeader from './components/TodoHeader';
import TodoList from './components/TodoList';
import TodoFooter from './components/TodoFooter';
export default {
data(){
return{
todos: [{title: 'eat'.complete: true },
{ title: 'sleep'.complete: false },
{ title: 'Knock code'.complete: true}}},components:{
TodoHeader,
TodoList,
TodoFooter
}
}
</script>
Copy the code
TodoList.vue
Receiving data, V-for traverses the array
<template>
<ul class="todo-main">
<TodoItem v-for="(todo, index) in todos" :key="index" :todo="todo"/>
</ul>
</template>
<script>
import TodoItem from './TodoItem';
export default {
props: {
todos: Array
},
components:{
TodoItem
}
}
</script>
Copy the code
TodoItem.vue
Get data, bidirectional binding
<template>
<li>
<label>
<input type="checkbox" v-model="todo.complete" />
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" style="display:none">delete</button>
</li>
</template>
<script>
export default {
props: {todo: Object,}}</script>
Copy the code
show
5.2 Dynamic Interaction – Add operations at the front
App.vue
Define addTodo function to add
<template>
<TodoHeader :addTodo="addTodo" />
</template>
<script>
export default {
methods: {addTodo(todo){
this.todos.unshift(todo); }}},</script>
Copy the code
TodoHeader.vue
V-model bidirectional binding data definition add mouse click event function
- Checking input Validity
- Generates a TOdo object based on the input
- Added to the todos
- Remove the input
<template>
<div class="todo-header">
<input type="text" placeholder="Please enter your task name and press Enter to confirm." v-model="title" @keyup.enter="add"/>
</div>
</template>
<script>
export default {
props: {addTodo: Function
},
data(){
return {
title: ' ',}},methods: {add(){
// 1. Check the input validity
const title = this.title.trim();
if(! title){ alert("Please enter the content");
return;
}
// 2. Generate a todo object from the input
const todo = {title, complete:false};
// 3. Add todos
this.addTodo(todo);
// 4. Clear the input
this.title = ' '; }}}</script>
Copy the code
5.3 Dynamic Interaction — Intermediate delete operation + select color change
Select color change mouse movement event to change background color, icon display to hide delete element operation
App.vue
DeleteTodo Deletes the specified element in an array
<template>
<TodoList :todos="todos" :deleteTodo="deleteTodo" />
</template>
<script>
export default {
methods: {deleteTodo(index){
this.todos.splice(index, 1); }}},</script>
Copy the code
TodoList.vue
Pass the label, delete the function
<template>
<ul class="todo-main">
<TodoItem v-for="(todo, index) in todos" :key="index" :todo="todo" :index="index" :deleteTodo="deleteTodo" />
</ul>
</template>
<script>
import TodoItem from './TodoItem';
export default {
props: {
todos: Array.deleteTodo: Function
},
components:{
TodoItem
}
}
</script>
Copy the code
TodoItem.vue
Mouse movement event function operates background color change, icon display hide delete button click event function
<template>
<li @mouseenter="handleEnter(true)" @mouseleave="handleEnter(false)" :style="{background: bgColor}">
<label>
<input type="checkbox" v-model="todo.complete" />
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" v-show="isShow" @click="deleteItem">delete</button>
</li>
</template>
<script>
export default {
props: {todo: Object.index: Number.deleteTodo: Function
},
data(){
return {
bgColor: 'white'.isShow: false}},methods: {
handleEnter(isEnter){
if(isEnter){
this.bgColor='#aaa';
this.isShow = true;
}else{
this.bgColor='white';
this.isShow = false; }},deleteItem(){
const {todo, index, deleteTodo} = this;
if(window.confirm('Sure to delete'${todo.title}"A `)){ deleteTodo(index); }}}},</script>
Copy the code
5.4 Dynamic Interaction — Select All at the bottom + Delete operation (difficult points)
App.vue
<template>
<TodoFooter :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAllTodos="selectAllTodos"/>
</template>
<script>
export default {
methods: {addTodo(todo){
this.todos.unshift(todo);
},
deleteTodo(index){
this.todos.splice(index, 1);
},
deleteCompleteTodos(){
this.todos = this.todos.filter(todo= >! todo.complete); },selectAllTodos(check){
this.todos.forEach(todo= >todo.complete = check); }}},</script>
Copy the code
TodoFooter.vue
Proficiency with computed attributes
<template>
<div class="todo-footer">
<label>
<input type="checkbox" v-model="isAllCheck" />
</label>
<span>
<span>Completed {{completeSize}}</span> / 全部{{ todos.length }}
</span>
<button class="btn btn-danger" v-show="completeSize" @click="deleteCompleteTodos">Clear completed tasks</button>
</div>
</template>
<script>
export default {
props: {
todos: Array.deleteCompleteTodos: Function.selectAllTodos: Function,},computed: {
completeSize() {
return this.todos.reduce((preTotal, todo) = > preTotal + (todo.complete?1:0), 0);
},
isAllCheck: {
get(){
return this.completeSize===this.todos.length && this.completeSize>0
},
set(value){
this.selectAllTodos(value); }}},methods: {
deleteAll(){},}};</script>
Copy the code
Summarize the TodoList case
-
Componentized coding process:
-
Split up static components: Components are split up by function points, with names that do not conflict with HTML elements.
-
Implementing dynamic components: Consider where the data is stored, whether the data is used by a component or by several components:
1). A component is in use: just place it on the component itself.
2). Some components are in use: put them on their common parent (state promotion).
-
Implement interactions: Start with binding events.
-
-
Props applies to:
-
Parent component ==> Child component communication
-
Child component ==> Parent component communication (requires parent to give child a function first)
-
-
When using the V-model, remember that the value bound to the V-model cannot be the same as the value transmitted by props, because the props cannot be modified.
-
Vue does not raise an error when the props passes a value of the object type, but this is not recommended.
webStorage
-
The storage size is generally around 5MB (depending on the browser).
-
The browser implements the localStorage mechanism through the window. sessionStorage and window. localStorage properties.
-
The API:
-
xxxxxStorage.setItem(‘key’, ‘value’); The method takes a key and value as arguments, adds the key-value pair to the store, and updates the corresponding value if the key name exists.
-
xxxxxStorage.getItem(‘person’); This method takes a key name as an argument and returns the value of the key name.
-
xxxxxStorage.removeItem(‘key’); The method takes a key name as an argument and removes the key name from storage.
-
Xxxxxstorage.clear () This method clears all data in the storage.
-
-
Remark:
- The contents of SessionStorage will disappear when the browser window closes.
- The content stored in LocalStorage must be manually cleared before it disappears.
xxxxxStorage.getItem(xxx)
If the value corresponding to XXX cannot be obtained, the return value of getItem is null.JSON.parse(null)
Is still null.
6. Local storage version
App.vue
<script>
export default {
data(){
return {
// Read todos from localStorage
todos: JSON.parse(window.localStorage.getItem('todos_key') | |'[]')
// todos: [
// {title: '吃饭', complete: false},
// {title: 'sleep ', complete: true},
// {title: '敲代码', complete: false}
// ]}},watch: { / / monitor
todos: {deep: true.// Deep monitoring
handler: function(value){
// Save the latest todos json data to localStorage
window.localStorage.setItem('todos_key'.JSON.stringify(value))
}
}
},
}
</script>
Copy the code
Project code https://github.com/yk2012/vue_demo/tree/main/demo3_TodoList
Finally, welcome to my column and make friends with YK bacteria