vue todos

<section class="todoapp">
  <header class="header">
    <h1>todos</h1>
    <input class="new-todo"
      autofocus autocomplete="off"
      placeholder="What needs to be done?"
      v-model="newTodo"
      @keyup.enter="addTodo">
  </header>
  <section class="main" v-show="todos.length" v-cloak>
    <input id="toggle-all" class="toggle-all" type="checkbox" v-model="allDone">
    <label for="toggle-all"></label>
    <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> {{ remaining | pluralize }} left
    </span>
    <ul class="filters">
      <li><a href="#/all" :class="{ selected: visibility == 'all' }">All</a></li>
      <li><a href="#/active" :class="{ selected: visibility == 'active' }">Active</a></li>
      <li><a href="#/completed" :class="{ selected: visibility == 'completed' }">Completed</a></li>
    </ul>
    <button class="clear-completed" @click="removeCompleted" v-show="todos.length > remaining">
      Clear completed
    </button>
  </footer>
</section>


//保存成一个变量,好处 如果有变动,改动vlaue值就行
var STORAGE_KEY = 'todos' 
var todoStorage = {
  fetch: funciton (){
  //获取本地存储
  var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
  todos.forEach(function (todo, index){ //获取每个todo信息
    todo.id = index  
  //todo对应的index  --id  0 1 2 3   
  //:key="todo.id"
    
   })
   
   todoStorage.uid = todos.length
   return todos
  
  
},
  //保存变动后todos保存到 localStorage,需要转化成string
  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
      })
  }
}


var app = new Vue({
  data: {
    //页面需要的数据
    todos: todoStorage.fetch(),
    //
    newTodo: '',
   //当前必须存在一个状态
    visibility: 'all',
    editedTodos: null
   
  },
  //监听data属性
  //监听到todos整体有变化,不就知道是不是有变化, 将改变后的todos本地存储
  watch: {
    todos:{
      //监听todos变化, 回调函数接受两参数,新值和旧值
      handler: function(todos){
          todoStorage.save(todos)
      },
      deep: true
    }
  },
  
  
  computed: {
    filteredTodos: function() {
      return filters[this.visibility](this.todos)
    },
    remianing: function() {
      return filters.active(this.todos).length
    },
    allDone: function() {
      get: function() {
        return this.remiaing === 0
      },
        set: function() {
          this.todos.forEach(function(todo){
            //???????   value  ---v-model  为啥在data中没有    comple又那体现的
            todo.completed = value
          })
        }
    }
  
  },
  
  //过滤 item的值
  filters: {
    
    pluralize: function(n) {
       return n=== 1 ? 'item': 'items'
    }
    
  },
  
  
  methods: {
    //用户输入内容后回车 操作
    addTodo : function(){
      var value = this.newTodo && this.newTodo.trim()
      //特殊情况: 没有输入内容 return
      if(!value){
        return
      }
      //有内容 ,加入到todos 中
      this.todos.push({
        id: todoStorage.uid++,
        title: value,
        completed: false
      })
      //将 变量清空, 下一次使用
      this.newTodo = ''
    },
    //点击 x,删除li  也就是数组中找出一个指定元素  删除
    
    removeTodo: function(todo) {
      // splice(2,1) 删除替换数组中的第2 个元素的
      //indexOf()  返回一个数组中给定元素的对应索引
      this.todos.splice(this.todos.splice(todo),1)
    },
    
    editTodo: function(todo) {
      
    },
    
    
    doneTodo: function(todo) {
        if(!this.editedTodo){
          return 
        }
      this.editedTodo = null
      
    },
    //点击键盘上的esc时 取消编辑
    cancelEdit: function() {
      
    },
    //未选中时 
    removeCompleted: function() {
      
    } 
    


//双击输入框 编辑
 editTodo: function (todo) {
      this.beforeEditCache = todo.title
      this.editedTodo = todo
    },
// ???? 输入后,失去焦点(点击别处)或者 键盘点击enter时 完成
    doneEdit: function (todo) {
      if (!this.editedTodo) {
        return
      }
      this.editedTodo = null
      todo.title = todo.title.trim()
      if (!todo.title) {
        this.removeTodo(todo)
      }
    },
 //点击键盘上的esc时 取消编辑
    cancelEdit: function (todo) {
      this.editedTodo = null
      todo.title = this.beforeEditCache
    },
//未勾选时
    removeCompleted: function () {
      this.todos = filters.active(this.todos)
    }

  }
  
})






//路由切换

function  onHashChange() {
  //当页面路由发生改变,要找到当前页面url中的hash
  // hash === all actived completed
  var visibility = window.location.hash.replace(/#\/?/, '') 
  //hash 存在,是all actived completed 之间任意个, 改变vue实例中的data-visibility
  if(filters[visibility]){
    app.visibility = visibility
    
  }else {
    //如果当前hash 是不存在的,那么默认为 all
    window.location.hash = ''
    app.visibility = 'all'
  }
}


// 自定义指令
// 如果绑定指令元素上的value 存在, 为焦点状态
  directives: {
    'todo-focus': function (el, binding) {
      if (binding.value) {
        el.focus()
      }
    }
  }
})

//监听hashchange事件, 执行函数onHashChange

window.addEventListener('hashchange', onHashChange)
onHashChange()

app.$mount('.todoapp')



[v-cloak] { display: none;}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容