<body>
<div id="box">
<div class="text">
<input type="text" placeholder="回车即可添加内容" v-model="newOne.title" @keyup.enter="add">
</div>
<p>
任务总数:{{arr.length}}个,还有{{noCheck}}个任务没有完成;[<span class="wc" @click="complete()">删除已完成</span>]
</p>
<p v-show="!arr.length">还没有任务,快添加一个吧</p> <br>
<a href="#all" :class="{on:visibility == 'all'}">全部任务</a>
<a href="#unfinish" :class="{on:visibility == 'unfinish'}">未完成</a>
<a href="#finished" :class="{on:visibility == 'finished'}">已完成</a>
<h3>任务列表</h3>
<ul>
<li v-for="(item, index) in filterArr" :key="item.id">
<input type="checkbox" v-model="item.isChecked">
<span @dblclick='goEdit(item)' v-show="!item.edit">{{item.title}}</span>
<input type="text" v-show="item.edit" v-model="item.title" v-focus="item.edit"
@keyup.enter="item.edit=false" @keyup.esc="goEnter(item)">
<button @click="del(item.id)">X</button>
</li>
</ul>
</div>
<script src="vue.js"></script>
<script>
let vm = new Vue({
el: "#box",
data: {
arr: [ ],
newOne: {id:Date.now(), title: '', isChecked: false, edit: false },
oldtitle: "",
mytitle: "",
visibility: 'all' },//通过hash变化赋值给该属性,在计算属性里
methods: {
goEdit(item) {
this.oldtitle = item.title
item.edit = true
},
goEnter(item) {
item.title = this.oldtitle;
oldtitle = ''
item.edit = false;
},
add() {
if (this.newOne.title) {
this.arr.push(this.newOne)
this.newOne = {id:Date.now(), title: '', isChecked: false, edit: false }
} else {
return; } },
del(id) {
let index= this.arr.findIndex((item) => {
return item.id==id });
this.arr.splice(index, 1)
},
complete() {
let temp = this.arr
this.arr = []
this.arr = temp.filter(item => {
return !item.isChecked
})
}
},
directives: {
focus: function (el, bind) {
if (bind.value) {
el.focus()
}
}
},
computed: {
noCheck: function () {
return this.arr.filter((item) => {
return !item.isChecked
}).length
},
filterArr: function () {//list根据hash值 过滤出新的数组
if (this.visibility == 'unfinish') {
return this.arr.filter((item) => {
return !item.isChecked })
}else if (this.visibility == 'finished') {
return this.arr.filter((item) => {
return item.isChecked })
}else{ return this.arr } } }, });
function watchHashChange() {
let myhash = location.hash.slice(1)
console.log('myhash:'+location.hash);//#all/unfinish/finish
vm.visibility = myhash }
watchHashChange()//一打开页面调用
window.addEventListener('hashchange', watchHashChange)
</script>
</body>
</html>
本地存储封装
<script>
// 封装两个方法:localStorage存储和获取
let store = {
save(key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
fetch(key) {
if (JSON.parse(localStorage.getItem(key))) {
return JSON.parse(localStorage.getItem(key))
} else {
return [];//第一次没有存储数据时
}
},
}
// let listDefault = [====>添加默认项,如果不需要不写即可,一旦添加不删除则不会消失
// { title: "吃饭", isChecked: false, edit: false },
// { title: "逛街", isChecked: false, edit: false } ]
// store.save('doArr',listDefault )
let list = store.fetch('doArr')
console.log(list);
new Vue({
el: "#box",
data: {
arr: list,
oldtitle: "",
mytitle: "",//不可以newOne.title,否则每一个新添的title不是独立的
},
methods: {
goEdit(item) {
this.oldtitle = item.title
item.edit = true
},
goEnter(item) {
item.title = this.oldtitle;
oldtitle = ''
item.edit = false;
},
add() {
let newOne = { title: this.mytitle, isChecked: false, edit: false }//只能在函数内声明新添加的对象
if (this.mytitle) {
this.arr.push(newOne)
this.mytitle = ""
} else {
return;
}
},
del(i) {
this.arr.splice(i, 1)
},
complete() {
let temp = this.arr
this.arr = []
this.arr = temp.filter(item => {
return !item.isChecked
})
}
},
directives: {
focus: function (el, bind) {
if (bind.value) {
el.focus()
}
}
},
computed: {
noCheck: function () {
return this.arr.filter((item) => {
return !item.isChecked
}).length
}
},
watch: {
// 只监控对象的变化,勾选后,刷新没有勾选效果
// arr: function(val){
// store.save('todolist',val)
// 深度监控:监控对象和对象属性的变化,勾选刷新依然有勾选效果
//如果 `arr` 发生改变,这个函数就会运行
arr: {
handler: function (val) {
store.save('doArr', val)
},
deep: true } }, })
</script>
```