标签:label :hover mouse 而不是 ant meta pst int string
代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="./static/css/bootstrap.css">
<title>vue_demo</title>
<style>
.router-link-active {
color: red !important;
}
</style>
</head>
<body>
<div id="app">
</div> <!--app -->
</body>
</html>
src/base.css
body { background: #fff; } .btn { display: inline-block; padding: 4px 12px; margin-bottom: 0; font-size: 14px; line-height: 20px; text-align: center; vertical-align: middle; cursor: pointer; box-shadow: inset 0 1px 0 rgba(225, 225, 225, 0.2), 0 1px 2px rgba(0, 0, 0,0.15); border-radius: 4px; } .btn-danger { color: #fff; background-color: #da4f49; border: 1px solid #bd362f; } .btn-danger:hover { color: #fff; background-color: #bd362f; } .btn:focus { outline: none; }
src/main.js
/** * Created by infaa on 2018/9/19. */ import Vue from ‘vue‘ import App from ‘./components/App‘ import store from ‘./store‘ import ‘./base.css‘ /* eslint-disable no-new */ new Vue({ el: ‘#app‘, render: h => h(App), store })
src/util/storageUtil.js
/** * Created by infaa on 2018/9/20. */ const TODO_KEY = ‘todos_key‘ export default { saveTodos (value) { window.localStorage.setItem(TODO_KEY, JSON.stringify(value)) }, readTodos () { return JSON.parse(window.localStorage.getItem(TODO_KEY) || ‘[]‘) } }
src/store/action.js
/** * Created by infaa on 2018/9/22. */ import {ADD_TODO, DELETE_TODO, SELECT_ALL_TODOS, CLEAR_ALL_COMPLETED, RECEIVE_TODOS} from ‘./mutation-types‘ import storeageUtil from ‘../util/storageUtil‘ export default { addTodo ({commit}, todo) { commit(ADD_TODO, {todo}) }, deleteTodo ({commit}, index) { commit(DELETE_TODO, {index}) }, selectAllTodos ({commit}, check) { commit(SELECT_ALL_TODOS, {check}) }, clearALLCompleted ({commit}) { commit(CLEAR_ALL_COMPLETED) }, reqTodos ({commit}) { // 模拟异步获取延迟1秒 setTimeout(() => { const todos = storeageUtil.readTodos() commit(RECEIVE_TODOS, todos) }, 1000) } }
src/store/getters.js
/** * Created by infaa on 2018/9/22. */ export default { totalCount (state) { return state.todos.length }, completeCount (state) { return state.todos.reduce((preTotal, todo) => { return preTotal + (todo.complete ? 1 : 0) }, 0) }, isAllSelected (state, getters) { return getters.totalCount === getters.completeCount && state.todos.length > 0 } }
src/store/index.js
/** * Created by infaa on 2018/9/22. */ import Vue from ‘vue‘ import Vuex from ‘vuex‘ import state from ‘./state‘ import mutations from ‘./mutations‘ import actions from ‘./actions‘ import getters from ‘./getters‘ Vue.use(Vuex) /* eslint-disable new-cap */ export default new Vuex.Store({ state, mutations, actions, getters })
src/store/mutation-types.js
/** * Created by infaa on 2018/9/22. * mutation 名称常量 */ export const ADD_TODO = ‘add_todo‘ export const DELETE_TODO = ‘delete_todo‘ export const SELECT_ALL_TODOS = ‘select_all_todos‘ export const CLEAR_ALL_COMPLETED = ‘clear_all_completed‘ export const RECEIVE_TODOS = ‘receive_todos‘ // 接收todos
src/store/mutation.js
/** * Created by infaa on 2018/9/22. */ import {ADD_TODO, DELETE_TODO, SELECT_ALL_TODOS, CLEAR_ALL_COMPLETED, RECEIVE_TODOS} from ‘./mutation-types‘ export default { [ADD_TODO] (state, {todo}) { state.todos.unshift(todo) }, [DELETE_TODO] (state, {index}) { state.todos.splice(index, 1) }, [SELECT_ALL_TODOS] (state, {check}) { state.todos.forEach(todo => (todo.complete = check)) }, [CLEAR_ALL_COMPLETED] (state) { state.todos = state.todos.filter(todo => (!todo.complete)) }, [RECEIVE_TODOS] (state, todos) { state.todos = todos } }
src/store/state.js
/** * Created by infaa on 2018/9/22. */ export default { todos: [] }
components/App.vue
<template> <div class="todo-container"> <div class="todo-wrap"> <TodoHeader></TodoHeader> <TodoList></TodoList> <TodoFooter></TodoFooter> </div> </div> </template> <script> import TodoHeader from ‘./TodoHeader.vue‘ import TodoList from ‘./TodoList.vue‘ import TodoFooter from ‘./TodoFooter.vue‘ // import storageUtil from ‘../util/storageUtil.js‘ export default { mounted () { // 发送命令到acitong,模拟异步获取todos数据,由action处理 this.$store.dispatch(‘reqTodos‘) }, components: { TodoHeader, TodoList, TodoFooter } // methods: { // // }, // watch: { // todos: { // deep: true, // handler: storageUtil.saveTodos // } // // } } </script> <style> .todo-container { width: 600px; margin: 0 auto; } .todo-container .todo-wrap { padding: 10px; border: 1px solid #ddd; border-radius: 5px; } </style>
components/TodoFooter.vue
<template>
<div class="todo-footer">
<label>
<input type="checkbox" v-model="isAllChecked">
</label>
<span>
<span>已完成{{completeCount}}</span>/全部{{totalCount}}
</span>
<button class="btn btn-danger" v-show="completeCount" @click="clearALLCompleted">清除已完成任务</button>
</div>
</template>
<script>
import {mapGetters, mapActions} from ‘vuex‘
export default {
computed: {
...mapGetters([‘totalCount‘, ‘completeCount‘, ‘isAllSeleted‘]),
isAllChecked: {
get () {
return this.$store.getters.isAllSelected
},
set (value) {
this.$store.dispatch(‘selectAllTodos‘, value)
}
}
},
methods: {
...mapActions([‘clearALLCompleted‘])
}
}
</script>
<style>
.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>
components/TodoHeader.vue
<template>
<div class="todo-header">
<input type="text" placeholder="请输入你的任务名称,按回车键确认"
v-model="inputTodo" @keyup.enter="addItem">
</div>
</template>
<script>
export default {
data () {
return {
inputTodo: ‘‘
}
},
methods: {
addItem () {
const title = this.inputTodo.trim()
if (!title) {
alert(‘title Kong‘)
return
}
const todo = {
title,
complete: false
}
this.$store.dispatch(‘addTodo‘, todo)
this.inputTodo = ‘‘ // 注意这里要操作this对象而不是函数内局部变量title
// 验证合法性 生成对象 添加 还原
}
}
}
</script>
<style>
.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.75), 0 0 8px rgba(82, 168, 236, 0.5);
}
</style>
components/TodoItem.vue
<template>
<li :style="{background: bgColor}" @mouseenter="handleEnter(true)" @mouseleave="handleEnter(false)">
<label>
<input type="checkbox" v-model="todo.complete">
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" @click="deleteItem" v-show="isShow">删除</button>
</li>
</template>
<script>
export default {
props: {
todo: Object,
index: Number
},
data () {
return {
isShow: false,
bgColor: ‘white‘
}
},
methods: {
deleteItem () {
const index = this.index
const todo = this.todo
if (window.confirm(`删除${todo.title}`)) {
this.$store.dispatch(‘deleteTodo‘, index)
}
},
handleEnter (isEnter) {
if (isEnter) {
this.isShow = true
this.bgColor = ‘grey‘
} else {
this.isShow = false
this.bgColor = ‘white‘
}
}
}
}
</script>
<style>
/*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>
components/TodoList.vue
<template>
<ul class="todo-main">
<TodoItem v-for="(todo,index) in todos" :todo="todo" :key="index" :index="index"></TodoItem>
</ul>
</template>
<script>
import {mapState} from ‘vuex‘
import TodoItem from ‘./TodoItem.vue‘
import storeageUtil from ‘../util/storageUtil‘
export default {
components: {
TodoItem
},
computed: {
...mapState([‘todos‘])
},
watch: {
todos: {
deep: true,
handler: storeageUtil.saveTodos
}
}
}
</script>
<style>
.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;
}
</style>
标签:label :hover mouse 而不是 ant meta pst int string
原文地址:https://www.cnblogs.com/infaaf/p/9691630.html