> 웹 프론트엔드 > CSS 튜토리얼 > Vue의 todoMVC 사용법에 대한 자세한 설명

Vue의 todoMVC 사용법에 대한 자세한 설명

php中世界最好的语言
풀어 주다: 2018-03-23 09:45:08
원래의
3151명이 탐색했습니다.

이번에는 Vue의 todoMVC 사용에 대한 자세한 설명을 가져오겠습니다. Vue의 todoMVC 사용 시 주의사항은 무엇인가요?

본 예제는 공식 홈페이지 예제의 스타일과 기능을 모방하여 제 나름대로 작성한 것입니다. 기본적으로 공식 홈페이지의 소스코드는 보지 않고, 커스텀 설명만 참고하였습니다. 단계별로 살펴보겠습니다. 공식 홈페이지 데모

구현 예정 기능

  1. 단일 항목의 할 일 추가

  2. 단일 항목의 할 일 삭제

  3. 할 일을 더블클릭하여 편집

  4. 단일 할 일이 완료되었습니다. 해당 스타일 상태 변경

  5. 모든 할일은 해당 스타일 상태 변경이 완료되었습니다

  6. 완료된 할일 모두 지우기

  7. Todo 할일 번호 표시

  8. 모든 할일, 완료된 할일, 미완료 할일 필터

Single add todo

<input type="text" class="todos_add" placeholder="What needs to be done?" 
@keyup.enter="addTodo($event.target)" //绑定enter事件
ref="currentInput">//操作input元素使enter一下之后清空输入框内容
로그인 후 복사
data() {//一些初始化数据
 return {
  todolists: [],
  dataStatus: ["All", "Active", "Completed"],
  dataStatusIndex: 0,
  whichShow: true,
  defaultShow: true
 }
},
addTodo(e) { //添加todo
 var val = e.value
 if (val === "") {return} //如果输入内容为空则立即返回
 this.todoLists = this.todoLists.concat({//使用concat这个api添加todo
  value: val, //输入内容
  isEditing: false, //是否在编辑状态
  isActive: false, //删除X图标是否激活
  isChecked: false //是否已完成
 })
 this.$refs.currentInput.value = "" //按下enter添加todo之后把输入框value清零
 window.localStorage.setItem("content",JSON.stringify(this.todoLists))//使用localStorage以JSON格式存储数据
},
로그인 후 복사

각 todo의 해당 상태는 작업에 의해 todo 상태가 변경되면 일률적으로 처리되지 않으므로 각 todo는 별도의 상태를 갖습니다. .

todo 단일 삭제

 <li class="content_todoList"
 v-for="(list,index) in todoLists" 
 @mouseover="list.isActive = true" //鼠标移入todo改变对应todo的isActive状态
 @mouseleave="list.isActive=false" //鼠标移出todo改变对应todo的isActive状态
 <span class="el-icon-close content_todoList_delete" 
 :class="{show: list.isActive}" //动态绑定class使鼠标移动到某一todo显示X图标
 @click="deleteTodo(index)"> //绑定删除单条todo事件
 </span>
</li>
로그인 후 복사
deleteTodo(index) { //删除单条todo
  this.todoLists.splice(index, 1)//使用splice的api
  window.localStorage.setItem("content",JSON.stringify(todoLists)) //以JSON格式存储数据//localStorage存储数据
},
로그인 후 복사

마우스 이동 및 제거 이벤트를 각 li 요소에 바인딩하여 각 todo의 isActive를 동적으로 변경한 다음 isActive를 사용하여 클래스를 동적으로 표시합니다.

두 번 클릭하여 할일 편집&&단일 할일이 완료되었습니다

<input type="checkbox" class="checkBox" 
v-model="list.isChecked">//双向绑定isChecked
<p class="content_todoList_main" 
@dblclick="toEdit(list)" //双击事件
v-show="!list.isEditing" //切换元素
:class="{deleted:list.isChecked}"> //动态绑定class该表已完成todo样式
{{list.value}}
</p>
<input type="text" class="content_todoList_main main_input" 
v-model="list.value" //双向绑定可输入value
v-show="list.isEditing" //切换元素
v-todo-focus="list.value" //自定义指令,双击之后自动focus对焦
@blur="unEdit(list)"> //绑定blur失去焦点事件
로그인 후 복사
methods: {
 toEdit(obj) { //使添加的todothing可编辑
  obj.isEditing = true
 },
 
 unEdit(obj) { //使添加的todothing不可编辑
  obj.isEditing = false
 },
}
directives: { //自定义focus指令,需要一个binding参数做判断
 "todo-focus": function (el, binding) {
  if (binding.value) {
   el.focus()
  }
 }
}
로그인 후 복사

각 할일의 isEditing 속성을 통해 표시 및 편집 가능 여부를 제어합니다. p를 더블클릭한 후 현재 할 일의 isEditing을 true로 변경합니다. 입력으로 표시되고 흐림 이벤트를 통해 초점이 false로 변경된 후 입력이 손실됩니다.

todo의 idChecked를 사용하여 완료 여부를 제어하여 스타일을 동적으로 변경합니다.

모든 할 일이 완료되었습니다

<span 
class="icon-down el-icon-arrow-down" //使用element库做向下箭头icon
v-show="todoLists.length>0" //通过todoLists控制是否显示向下箭头icon
@click="selectAllTodos"></span> //全部已完成事件
로그인 후 복사
selectAllTodos() { //设置所有todo为已完成,使用map的api通过todo的isChecked属性操作
 this.todoLists.map(todo => todo.isChecked = todo.isChecked ? false : true)
}
로그인 후 복사

할 일 할 일의 개수가 표시됩니다

<p class="data_times" v-show="times === 0"> //times为0显示item,大于0显示items,细节注定成败
 <span>{{times}}</span>&nbsp item left
</p>
<p class="data_times" v-show="times > 0">
<span>{{times}}</span>&nbsp items left</p>
로그인 후 복사
computed: {
 times() { //使用计算属性计算待办todos的次数 
  let todoArr = this.todoLists
  let times = 0
  for (let i = 0; i < todoArr.length; i++) {
   if (todoArr[i].isChecked === false) {
    times++
   }
  }
  return times
 }
},
로그인 후 복사

계산된 속성을 사용하여 todoList를 계산하고, for 루프를 사용하여 idChecked의 누적을 true로 선택하고, 마지막으로 시간을 반환합니다.

완료된 할 일 모두 지우기

<p class="data_clearTodos" 
@click="clearTodos" 
v-show="times < todoLists.length"> //如果待办事件次数小于总todoLists长度就显示“clear completed”
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >clear completed</a>
</p>
<p class="data_clearTodos" 
@click="clearTodos" 
v-show="times === todoLists.length"> //如果待办事件次数等于总todoLists长度就显示“clear completed”
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ></a>
</p>
로그인 후 복사
clearTodos() { //清空已完成的todoLists,使用filter的api进行筛选
 this.todoLists = this.todoLists.filter(todo => todo.isChecked === false)
 window.localStorage.setItem("content",JSON.stringify(this.todoLists)) //以json格式存储数据
},
로그인 후 복사

할 일의 시간이 todoList의 길이보다 작으면 완료된 할 일이 있음을 증명하며, 같으면 "완료됨 삭제"가 표시될 수 있음을 의미합니다. 완료된 할 일이 없습니다.

3가지 상태 필터링

모든 할 일, 완료된 할 일, 완료되지 않은 할 일 필터링

<li class="content_todoList" 
v-show="defaultShow || (whichShow?list.isChecked:!list.isChecked)">
<p class="data_status">
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 
 :class="{active: index === dataStatusIndex}" //动态class实现tab切换
 v-for="(item ,index) in dataStatus" v-for循环
 @click="switchStatus(index)" //切换不同tab显示内容
 :key="index">
  {{item}}
 </a>
</p>
로그인 후 복사
switchStatus(index) { //通过if条件判断操作
 this.dataStatusIndex = index
 if (this.dataStatus[index] === "Active") {
  this.defaultShow = false
  this.whichShow = false
 } else if (this.dataStatus[index] === "Completed") {
  this.defaultShow = false
  this.whichShow = true
 } else if (this.dataStatus[index] === "All") {
  this.defaultShow = true
 }
},
로그인 후 복사

if 조건문을 동시에 판단하려고 왔는데, 아직 다른 해결 방법은 생각하지 못했습니다. 할 일을 다른 상태로 표시하려면 삼항 연산 연산자와 li 요소의 or 연산자를 사용하세요.

완전한 코드

<style>
 * {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
 }
 input {
  outline: none;
 }
 ul,
 li,
 ol {
  list-style: none;
 }
 #app {
  width: 800px;
  height: 900px;
  margin: 0 auto;
  text-align: center;
  background-color: rgb(245, 245, 245);
  padding: 24px 0;
 }
 #app .header {
  font-size: 48px;
 }
 .content {
  width: 72%;
  margin: 0 auto;
  box-shadow: 0 3px 3px 2px rgba(0, 0, 0, 0.25);
  position: relative;
 }
 .icon-down {
  position: absolute;
  font-size: 24px;
  top: 16px;
  left: 16px;
  cursor: pointer;
 }
 #app .content .todos_add {
  width: 100%;
  height: 56px;
  padding: 16px 56px;
  font-size: 24px;
  border: 1px solid transparent;
 }
 .content_todoLists {
  position: relative;
  z-index: 3;
 }
 .content_todoList {
  display: flex;
  flex-direction: row;
  border-top: 1px solid #ccc;
  font-size: 24px;
  padding: 8px;
  background-color: white;
  align-items: center;
 }
 .checkBox {
  width: 20px;
  height: 20px;
  margin-left: 10px;
 }
 .content_todoList_main {
  flex: 1;
  text-align: left;
  margin-left: 16px;
  font-size: 20px;
  padding: 6px 0;
 }
 .main_input {
  position: relative;
  z-index: 1;
 }
 .content_todoList_delete {
  position: absolute;
  right: 16px;
  color: rgb(252, 55, 55);
  font-weight: 500;
  display: none;
  cursor: pointer;
 }
 .show {
  display: block;
 }
 .deleted {
  text-decoration-line: line-through;
  color: #bbb;
 }
 .show:hover {
  color: rgb(255, 0, 0);
  font-weight: 700;
 }
 ::-moz-placeholder {
  color: rgb(221, 218, 218);
 }
 ::-webkit-input-placeholder {
  color: rgb(221, 218, 218);
 }
 :-ms-input-placeholder {
  color: rgb(221, 218, 218);
 }
 .data {
  display: flex;
  justify-content: space-between;
  padding: 8px;
  font-size: 14px;
  font-weight: 300;
  color: rgb(145, 145, 145);
 }
 a {
  text-decoration: none;
  color: rgb(145, 145, 145);
 }
 .data_times {
  width: 73px;
 }
 .data_clearTodos {
  width: 142px;
 }
 .data_status a {
  display: inline-block;
  border: 1px solid transparent;
  border-radius: 2px;
  padding: 1px 4px;
  margin: 0 2px;
 }
 .data_status a:hover {
  border-color: #bbb;
 }
 .data_clearTodos a:hover {
  text-decoration-line: underline;
 }
 .active {
  box-shadow: 0 0 1px black;
 }
</style>
로그인 후 복사
<body>
 <p id="app">
  <header class="header">todos</header>
  <p class="content">
   <span class="icon-down el-icon-arrow-down" 
   v-show="todoLists.length>0" 
   @click="selectAllTodos">
   </span>
   <input type="text" class="todos_add" placeholder="What needs to be done?" 
   @keyup.enter="addTodo($event.target)" 
   ref="currentInput">
   <ul class="content_todoLists">
    <li v-for="(list,index) in todoLists" class="content_todoList" 
    @mouseover="list.isActive = true" 
    @mouseleave="list.isActive=false"
    v-show="defaultShow || (whichShow?list.isChecked:!list.isChecked)">
     <input type="checkbox" class="checkBox" v-model="list.isChecked">
     <p class="content_todoList_main" @dblclick="toEdit(list)" v-show="!list.isEditing" :class="{deleted:list.isChecked}">
      {{list.value}}
     </p>
     <input type="text" class="content_todoList_main main_input" 
     v-model="list.value" 
     v-show="list.isEditing" 
     v-todo-focus="list.value"
     @blur="unEdit(list)">
     <span class="el-icon-close content_todoList_delete" :class="{show: list.isActive}" @click="deleteTodo(index)"></span>
    </li>
   </ul>
   <p class="data" v-show="todoLists.length>0">
    <p class="data_times" v-show="times === 0">
     <span>{{times}}</span>&nbspitem left
    </p>
    <p class="data_times" v-show="times > 0">
     <span>{{times}}</span>&nbspitems left
    </p>
    <p class="data_status">
     <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" :class="{active:index === dataStatusIndex}" v-for="(item,index) in dataStatus" @click="switchStatus(index)" :key="index">
      {{item}}
     </a>
    </p>
    <p class="data_clearTodos" @click="clearTodos" v-show="times < todoLists.length">
     <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >clear completed</a>
    </p>
    <p class="data_clearTodos" @click="clearTodos" v-show="times === todoLists.length">
     <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ></a>
    </p>
   </p>
  </p>
 </p>
</body>
<script>
 let vm = new Vue({
  el: "#app",
  data() {
   return {
    todoLists: [],
    dataStatus: ["All", "Active", "Completed"],
    dataStatusIndex: 0,
    whichShow: true,
    defaultShow: true
   }
  },
  computed: {
   times() { //使用计算属性计算待办todos的次数 
    let todoArr = this.todoLists
    let times = 0
    for (let i = 0; i < todoArr.length; i++) {
     if (todoArr[i].isChecked === false) {
      times++
     }
    }
    return times
   }
  },
  methods: {
   toEdit(obj) { //使添加的todo可编辑
    obj.isEditing = true
   },
   unEdit(obj) { //使添加的todo不可编辑
    obj.isEditing = false
   },
   addTodo(e) { //添加todo
    var val = e.value
    if (val === "") {
     return
    } //如果输入内容为空则立即返回
    this.todoLists = this.todoLists.concat({ //使用concat这个api添加todo
     value: val, //输入内容
     isEditing: false, //是否在编辑状态
     isActive: false, //删除X图标是否激活
     isChecked: false //是否已完成
    })
    this.$refs.currentInput.value = "" //按下enter添加todo之后把输入框value清零
    window.localStorage.setItem("content", JSON.stringify(this.todoLists)) //使用localStorage以JSON格式存储数据
   },
   deleteTodo(index) { //删除todo
    this.todoLists.splice(index, 1)
    window.localStorage.setItem("content", JSON.stringify(this.todoLists)) //以json格式存储数据
   },
   switchStatus(index) { //试下下方三个状态切换,略麻烦
    this.dataStatusIndex = index
    if (this.dataStatus[index] === "Active") {
     this.defaultShow = false
     this.whichShow = false
    } else if (this.dataStatus[index] === "Completed") {
     this.defaultShow = false
     this.whichShow = true
    } else if (this.dataStatus[index] === "All") {
     this.defaultShow = true
    }
   },
   clearTodos() { //清空已完成的todoLists
    this.todoLists = this.todoLists.filter(todo => todo.isChecked === false)
    window.localStorage.setItem("content", JSON.stringify(this.todoLists)) //以json格式存储数据
   },
   selectAllTodos() { //设置所有todo为已完成
    this.todoLists.map(todo => todo.isChecked = todo.isChecked ? false : true)
   }
  },
  directives: { //自定义focus指令
   "todo-focus": function (el, binding) {
    if (binding.value) {
     el.focus()
    }
   }
  },
  created() {
   let myStorage = window.localStorage.getItem('content')
   this.todoLists = JSON.parse(myStorage) || [] //因为todoLists初始值是null,使用或运算符,如果为null设为空数组
  }
 })
</script>
로그인 후 복사

이 기사의 사례를 읽으신 후 방법을 마스터하셨다고 믿습니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!

추천 도서:

Angular2 상위-하위 컴포넌트 통신 방법

자바스크립트 코드 최적화에 대한 자세한 설명

위 내용은 Vue의 todoMVC 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿