vue 从入门到精通之【数据操作(data,methods,computed,watch)+filter】(二)

11 篇文章 0 订阅
订阅专栏
10 篇文章 1 订阅
订阅专栏

Vue.prototype

vm.$watch 设置监听器,和直接在配置项中写的 watch 类似

vm.$set 设置响应式数据的值

vm.$delete 删除某个响应式数据

vm.$destroy 销毁这个组件/实例 会触发 beforeDestory 和 destroyed 周期函数

vm.$forceUpdate 强制通知组件更新「一般响应式数据更改后,组件会更新;但是非响应式数据更新后,我们也想让组件更新,可以基于这个办法」

vm.$mount 把编译后的内容挂载到某个容器中

vm.$nextTick 响应式数据更新,视图重新渲染,等到虚拟DOM已经变为真实DOM后触发这个函数

vm .emit/on/$off 发布订阅,实现父子组件通信

vm.$once 监听一个事件「只触发一次,原理是在第一次触发完,就移除了事件绑定」

Vue组件

创建 xxx.vue 就是创建一个vue组件,每一个vue组件都是 VueComponent 这个类的实例「而VueComponent是Vue的子类」 在组件的周期函数或者方法中,基于this就可以获取这个组件的实例

私有属性:和Vue实例具备相同的私有属性和特点

data设置的值是响应式数据,会挂载到实例上

methods设置的方法也会挂载到实例上,不是响应式数据

props接收的属性也会挂载到实例上,不是响应式数据

computed计算属性也会挂载到实例上,不是响应式数据

filters设置的函数,并没有挂载到实例上,而是在模板编译的时候,直接把函数执行,把返回结果渲染编译了

小技巧:

实例.proto -> VueComponent.prototype -> Vue.prototype

所以只要我们在Vue.prototype设置一些东西,这样所有组件最后都可以基于“this.xxx”获取到设置的东西,例如:

Vue.prototype.$api = {};
this.$api.xxx

data

基于data构建的数据,会自动挂载到vue的实例上「vm.xxx去访问这些数据」;而且这些数据是被劫持监听的「可以看到get/set」,这样的数据我们称之为“响应式数据”:响应式数据更新,视图会自动重新渲染!!

  • 默认情况下,初始化vue的实例,会把data中的数据进行深度遍历和劫持...

  • 对于数组数据来讲
    • 数组本身会被get/set vm.arr=xxx会通知视图渲染

    • 数组中的索引不会get/set,所以 vm.arr[0]=xxx不会通知视图渲染

    • vue重写了7个数组的方法 pop / push / shift / unshift / reverse / sort / splice ,操作这7个方法,在改变数组内容的同时,也会通知视图重新渲染;操作其它方法,不会通知视图渲染...

Object.defineProperty() 双向数据绑定的原理(vue2)

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性 Object.defineProperty(obj, prop, desc)

  1. obj 需要定义属性的当前对象

  2. prop 当前需要定义的属性名

  3. desc 属性描述符 一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。
    • writable:是否可以修改

    • enumerable:描述属性是否会出现在for in 或者 Object.keys()的遍历中(是否可枚举)在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的。可枚举性决定了这个属性能否被for…in查找遍历到。内置的属性是不可枚举的,所以不能被for…in访问到

    • configurable:描述属性是否配置,以及可否删除

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

核心:通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的

要实现mvvm的双向绑定,就必须要实现以下几点:

  1. 实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者

  2. 实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

  3. 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

  4. mvvm入口函数,整合以上三者

props

在子组件的模板内不能直接引用父组件的数据。

父组件的数据需要通过 prop 才能下发到子组件中.也就是说props是子组件访问父组件数据的唯一接口。

父组件通过v-bind向子组件传值,子组件通过props来获取父组件传递过来的值,被引用的就是子组件

methods

在Vue中,methods被命名为方法,它也是让我们调用在对象上下文中的函数,它可以操作对象中包含的数据。

函数必须在Vue中的methods属性下添加。这个属性没有依赖缓存

<template>
.......
<button @click="myMethods1()">
<button @click="myMethods2(31)">
.......
</teplate>
<script>
......
methods:{
   myMethods1:function(){
  alert("I am methods1")
   },
   
   myMethods2:function(num){
  alert("I am methods"+num)
   },
 
}
......
</script>

computed

computed:计算属性。 当依赖某些状态(data中的数据)发生变化时,优先选择使用computed

计算属性可用于快速计算视图( View )中显示的属性。这些计算将被缓存,并且只在需要时更新。

计算属性该属性里面的方法必须要有return返回值,这个返回值就是(value值)。

  1. 计算后属性不需要在data中重复定义

  2. 计算后属性必须渲染后,绑定的方法才会生效这里指就是定义后的变量名在上面html中显示

  3. 计算后属性绑定的方法中的任意变量值更新,方法都会被调用比如说方法中一个变量A,变量A变了函数会重新调用

  4. 计算后属性为只读属性(不可写)计算后属性为只读属性

watch(监听)

用来解决beforeUpdate, updated两个钩子里修改状态导致死循环的问题,采用watch

监测可能异步改变值得时候

  1. 监听绑定的属性,该属性可以get、set

  2. 监听的属性一旦发生值更新,绑定的方法就会被调用

  3. 监听的属性是已定于的属性必须在data中定义

在vue中,使用watch来响应数据的变化。watch的用法大致有三种。

  1. 直接写一个监听处理函数,当每次监听到 Uname 值发生改变时,执行函数。同样是写在script中,与methods同级

其中使用v-model使用到的参数需要先在data中申明一下,例如上面写的例子,data与methods也是同级关系,写在script中,例如:

<template>
.......
<input type="text" v-model="Uname">
.......
</teplate>
<script>
......
watch:{
   Uname(newValue, oldValue){
  alert(newValue)
  alert(oldValue)
   }
 
}
......
</script>

  1. Immediate和handler。

当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。

比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate设为true

watch:{
   Uname(newValue, oldValue){
  alert(newValue)
  alert(oldValue)
   },
   immediate: true
}

immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。

  1. deep。

当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。

<template>
.......
<input type="text" v-model="person.name">
.......
</teplate>
<script>
.......
data(){
  return{
 person:{
      name:'',
      age:'',
      sex:''
 }
  }
}
......
watch:{
   person:{
  handler(newValue, oldValue){
    alert(newValue)
    alert(oldValue)
     },
     deep:true,
     immediate:true
 }
 
}
......
</script>
watch:{
   'person.name':{
  handler(newValue, oldValue){
    alert(newValue)
    alert(oldValue)
     },
     deep:true,
     immediate:true
 } 
}

设置deep: true 则可以监听到cityName.name的变化,此时会给cityName的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,可以使用字符串的形式监听对象属性,这样只会给对象的某个特定的属性加监听器。

数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。

filters过滤器

  • 过滤器方法中的this不再是实例,而是window

  • 视图中使用过滤器 { 传递的值(多个值用逗号分隔)过滤器方法名},过滤器方法执行返回的是啥,视图中就渲染啥...

  • 和methods一样,每一次视图渲染,过滤器方法都需要执行

  • 一般只用于某个数据的格式化处理「当然我们可以使用性能更好的计算属性去代替它」

自定义过滤器 多个过滤器可以连用 {{}}、和v-bind能用过滤器,其他指令不能用,注意:过滤器不能用于v-model 等

<!-- 在双花括号中 -->
 {{ message | capitalize }}
 
 <!-- 在 `v-bind` 中 -->
 <div v-bind:id="rawId | formatId"></div>

    {{msg|toDo("12","5")}}
    
    {{msg|toDoa|toDob}}

全局过滤器:

Vue.filter('capitalize',function (val){
           let firstcap=val.slice(0,1).toUpperCase();
           let lastcap=val.slice(1);
           return firstcap+lastcap;
})

本地过滤器:

<div id="app">
   {{msg | capitalize('aaa','123')}}
   
   {{msg | capitalize}}
  </div>
  <div id="app2">
   {{msg | capitalize}}
  </div>
  <script>
//   2.0全局过滤器---->可以作用在任何vue实例上
    Vue.filter('capitalize',function (val,str="",num=""){
                 let firstcap=val.slice(0,1).toUpperCase();
                 let lastcap=val.slice(1);
     
                 return firstcap+lastcap+str+num;
             })
         
   var vm=new Vue({
    el:"#app",
    data:{
     msg:"apple"
    },
    methods:{
     
    },
filters:{
     capitalize(val){//局部过滤器
       let firstcap=val.slice(0,1).toUpperCase();
                   let lastcap=val.slice(1);
       
                   return firstcap+lastcap;
     }
    }
   })
   
   var vm2=new Vue({
    el:"#app2",
    data:{
     msg:"orange"
    },
    methods:{
     
    }
   })
  </script>

computed计算属性对比于methods:

  1. computed响应式,而methods非响应;computed在调用时只有当其引用的响应式属性改变时才会调用函数重新计算值(存在缓存),而methods是一个函数,每次调用就是执行其函数式

  2. computed中的成员可以只定义一个函数作为只读属性,也可以自定义get/set作为读写属性

  3. computed以vue对象的属性形式存在

在实际开发中,使用computed和mothods往往都能起到作用——返回或处理一个我们要的值,但是适用场景不同;比如:当我们要去时刻监控一个视图层对应的数据层的值的变化时,使用computed就比较合理了,因为computed可缓存的,只要数据层所依赖的值不改变,computed就不会改变,而只要变了 ,computed的值就会实时更新到视图层上,即computed是响应式的。

而在这个例子中,如果使用watch也可以实现,但是那就是对视图层对应的数据层的值的依赖数据进行监听,发生变化时再调用相应的函数更改该值,那么watch和computed又有什么区别呢? 异同如下:

computed计算属性对比于watch侦听器:

  1. 相同点:都是vue对监听器的实现,都起到监听/依赖一个数据并进行处理的作用

  2. 在应用中,computed主要应用于同步数据,而watch是用来观测一个值的变化去实现一段开销较大的复杂业务逻辑或执行异步操作

  3. 能用computed时优先使用computed,避免当我们需要得到的值依赖于多个数据时多次调用watch的尴尬

  4. watch监听的值接收两个参数——新值、旧值 ,可以设置在初始化时调用

例:watch:监听一个属性值的变化并执行相应的函数

var vm = new Vue({
    el: '#demo',
  data: {
      firstName: 'Foo',
    lastName: 'Bar',
    fullName:"Foo Bar"
  },
  watch:{
    firstName:function(val){
      this.fullName = val+this.lastName
    },
    lastName:function(val){
      this.fullName = this.firstName+val
    }
  }
})

computed:依赖其他属性所计算出来的值

var vm  = new Vue({
  el:'#demo',
  data:{
        firstName: 'Foo',
    lastName:'Bar'
  },
  computed:{
    fullName(){
      return this.firstName+this.lastName;
    }
  }
})

高级用法

计算属性的setter

var vm = new Vue({
  el:'#demo',
  data:{
    firstName:'Foo',
    lastName:'Bar'
  },
  computed:{
    fullName:{
      get(){
          return this.firstName + '·' + this.lastName        
      },
      set(newVal){
        var name = NewVal.split('·')
        this.firstName = name[0];
        this.lastName = name[name.length-1]
      }
    }
  }
})
//运行vm.fullName = 'Kobe Bryant'时,set方法会被调用,vm.firstName和vm.lastName的值会被更新

侦听器的handler方法和immediate属性

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      console.log('第一次没有执行')
      this.fullName = val + '·' + this.lastName
    }
  }
})

如果想firstName在第一次被绑定的时候就执行:

watch: {
  firstName: {
    handler(val){
      console.log('第一次执行了')
      this.fullName = val + '·' + this.lastName
    },
    immediate:true//在watch中声明后立即执行handler
  }
}

侦听器的deep属性

var vm = new Vue({
  el:'#demo',
  data:{
    item:{
      a:'',
      b:''
    }
  },
  watch:{
    item:{
      handler(val){
        console.log('item.a changed')
      },
      immediate: true
    }
  }
})
//运行vm.item.a = '123',发现控制台没有打印“item.a changed”

改变item.a的值发现控制台没有打印字符串,这是因为vue无法检测到对象属性的添加或者删除。由于vue会在初始化实例时给实例的属性执行getter/setter转化过程,所以属性必须在data对象上存在才能让vue转换它,才能是响应式的

默认情况下watch只监听对对象的引用,如当this.item = {a: '123',b:'123'}执行时handler就会执行,

深度遍历:

watch: {
  obj: {
    handler(val) {
      console.log('item.a changed')
    },
      immediate: true,
      deep: true
  }
}

deep的作用是:在对象一层层往下遍历,每一层都加上侦听器

优化 但是使用deep属性会给每一层都加上监听器,性能开销可能就会非常大了。这样我们可以用字符串的形式来优化:

  watch: {
    'item.a': {
      handler(val) {
       console.log('item.a changed')
      },
      immediate: true
      // deep: true
    }
  }

直到遇到item.a属性,才会给该属性设置监听函数,提高性能。

源码实现:

/* @flow */

import { _Set as Set, isObject } from '../util/index'
import type { SimpleSet } from '../util/index'
import VNode from '../vdom/vnode'

const seenObjects = new Set()

/**
 * Recursively traverse an object to evoke all converted
 * getters, so that every nested property inside the object
 * is collected as a "deep" dependency.
 */
export function traverse (val: any) {
  _traverse(val, seenObjects)
  seenObjects.clear()
}

function _traverse (val: any, seen: SimpleSet) {
  let i, keys
  const isA = Array.isArray(val)
  if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {
    return
  }
  if (val.__ob__) {
    const depId = val.__ob__.dep.id
    if (seen.has(depId)) {
      return
    }
    seen.add(depId)
  }
  if (isA) {
    i = val.length
    while (i--) _traverse(val[i], seen)
  } else {
    keys = Object.keys(val)
    i = keys.length
    while (i--) _traverse(val[keys[i]], seen)
  }
}

如果设置this.deep == true,则触发每个深层对象的依赖,追踪其变化。traverse方法递归每一个对象或者数组,触发它们的getter,使得对象或数组的每一个成员都被依赖收集,形成一个“深(deep)”依赖关系。这个函数实现还有一个小的优化,遍历过程中会把子响应式对象通过它们的 dep.id 记录到 seenObjects,避免以后重复访问。

vue 解决computed修改data数据的问题
12-13
最近在做项目的时候遇见一个问题,computed修改data数据的时候会报错。报错的大概意思是,不可以修改data数据的属性值。查了一些答案,最终解决办法是需要用到set和get。看代码: data () { return { fold: false } } 我想修改fold的值,如果不用get和set就会报错!!! computed:{ listShow: { get: function () { if (!this.totalCount) { return false } return this.fold
Vue从入门到精通基础课程(视频).txt
06-05
该资源适合新接触Vue的人员进行学习,通过视频进行学习,更方便于理解。
VUE』11. 操作数组的方法(详细图文注释)
最新发布
MZH
04-04 1537
VUE』11. 操作数组的方法(详细图文注释)
vue从入门到精通.rar
03-30
vue入门教程系列源码,小白级别入门教程,包含12个小结的源代码。
vue从入门到精通
03-28
vue从入门到精通适合刚入职场的小白,也适合职场多年的前端高手,为您全方位打造
vue 3.0学习笔记(从入门到精通)
10-07
vue 3.0自我学习整理的笔记,有很大的参考价值,包括了所有的知识点,vue的开发环境搭建、组件开发、数据状态管理、vue route、组件之前数据传递等有关知识点
Vue 常用属性 datamethodscomputedwatch
小楼一夜听春雨,深巷明朝卖杏花
06-21 885
计算属性一般就是用来通过其他的数据算出一个新数据,而且它有一个好处就是, 它把新的数据缓存下来了,当其他的依赖数据没有发生改变,它调用的是缓存的数据,这就极大的提高了我 们程序的性能。会在创建新组件实例的过程中调用此函数(将里面定义的变量都放到实例里面去,你就可以使用this点出来,包括HTML里面就能够使用这些变量的)。选项中的数据一样,可以在组件的模板中使用(挂载到html中某个dom上面)。你要的数据名不需要在data里面去定义,但是数据还是需要的,你的数据都是从data里面拿到的。
一、VUE基础
敲代码的小小酥的博客
02-15 1174
一、初始Vue 官方的话不多说了,总之现在Vue大行其道,不得不学了,所以才要学习VueVue的应用大部分用于前后端分离,前端自启的项目。但是在学习前端单独分离之前,要先了解Vue的简单玩法,即前后端不分离,直接在html里引入Vue.js使用Vue的玩法。本篇主要讲这种单机版玩法。 在详细讲解之前,先说一下Vue的大概规则及简写方式。先看一下如何定义Vue: var vm= new Vue({ el:'#root', data:{ }, methods:{
vue中的data,computed,methods,created,mounted
qq_59541478的博客
09-07 5488
本文将介绍一下vue的基本结构中各分类的含义以及他们的执行顺序。(包括data,computed,methods,created,mounted
Vue学习计划-Vue2--Vue核心(三)methodscomputed
我愿化作繁星
12-01 708
Vue学习计划--Vue2(三)methodscomputed
Vue2中的绑定事件和事件修饰符
weixin_64770583的博客
07-13 1395
绑定事件和事件修饰符
vue 组件传值
m0_59070120的博客
03-30 600
1,父组件通过标签上:data=data方式定义传值,子组件通过props方法接受数据 2,祖先组件provide,后代组件inject接受 // 父级组件提供 'foo' var Provider = { provide: { foo: 'bar' }, // ... } // 子组件注入 'foo' var Child = { inject: ['foo'], created () { console.log(this.foo) // => "bar" } // ... } 3,$refs,
三、vue_options之datamethods属性选项
Sean_0819的博客
04-16 1052
也可以传入一个对象必须传入一个函数Vue的响应式系统劫持对象的修改或者访问通过{{counter}}访问counter从对象中获取到数据修改counter的值app中的{{counter}}也会发生改变具体这种响应式的原理,我们后面会有专门的篇幅来讲解。
Vue实例方法 - 数据 (vm.$watch、vm.$set、vm.$delete)
Smile_Tcode的博客
11-15 1300
Vue实例方法 - 数据 (vm.$watch、vm.$set、vm.$delete) 一、官网链接 vue 实例方法 - 数据 、为什么使用?   确保能触发 Vue 更新视图。(详见Vue.set等等) 三、用法: 1、vm.$watch: (1) 用法:vm.$watch( expOrFn, callback, [options] ) (2)参数: expOrFn:{Function | string} 被监听的:data中的变量 | 带返回的函数体(注意使用方式) callback:
vue入门到精通详解介绍(第一部分)data详细介绍
WYT11的博客
08-16 5771
第一章 引入vue脚本在html页面上 基本操作 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"
Vue2.0使用props传递数据data篇】
yuzhiboyouzhu的博客
11-28 9122
<body> <div id = 'app'> <div> <h3>正常的数据</h3> <p> 组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用props把数据传给子组件 </p> </div> <h
关于method中自定义方法无法使用this读取vuedata中的数据的解决办法
m0_56522868的博客
10-23 2783
本人比较熟悉的是后端,但是无奈老板让写前端,只能硬着头皮上,但是在写前端的时候经常遇到一个问题,就是this指向老是发生变化,由于现在身边没有敲代码的本本,就直接画个草图记录一下,解决的思路来自这篇文章:微信小程序——普通回调函数中this拿不到data数据_hinataneji的博客-CSDN博客 根据这位博主文章的思路,我们如果想要在回调函数中让this指向vue组件,有两种办法: 一种是使用箭头函数, 一种是定一个全局变量把this存储下来。 经过实际项目测试,两种方法都非常好用,今天在家
vue基础 指令篇
shjd_J的博客
07-09 271
Vue.js 1.Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架Vue是一个Vue是一个用于的框架Vue是一个用于构建用户界面得2.渐进式框架介绍a. Vue.js提供了很多的功能,但是这些功能并不是集成在一起的,而是分开的类似于Nodejs,拆分成很多个小模块b. 在项目中我们用到什么,就导入什么这样可以保证我们用到的最少c. 说人话:Vue相当于是一个五星级自助餐,我们想要用什么就拿什么,这样可以最大限度避免浪费资源(1)Vue是什么?js框架(2)Vue干什么用
vue入门)export default常用代理,method和data,createdcomputed
weixin_37778355的博客
01-07 3061
vue中export default里面常用的代理,声明变量,方法等
要求用到技术1:Vue数据绑定 + [methodscomputedwatchfilters,Vue事件] 技术2:Vue组件 技术3:Vue路由
06-09
好的,那就让我们来一步步实现一个简单的Vue小作品吧。我们可以实现一个简单的待办事项应用,用户可以添加待办事项、标记已完成的事项、删除待办事项等功能。这个应用将会用到Vue数据绑定、组件、路由等技术。我们先来安装VueVue CLI。 1. 安装VueVue CLI 首先,你需要在本地安装Node.js和npm。然后,在命令行中运行以下命令安装Vue CLI: ``` npm install -g @vue/cli ``` 安装完成后,你可以在命令行中运行以下命令创建一个新的Vue项目: ``` vue create my-todo-app ``` 根据提示选择你需要的配置,Vue CLI 将会自动生成一个基础的 Vue 项目。 2. 创建一个待办事项组件 接下来,我们要创建一个待办事项组件。在项目根目录下的 `src/components` 中创建一个新的文件 `TodoItem.vue`。在这个文件中,我们将创建一个单个待办事项的组件。 ```html <template> <div class="todo-item"> <input type="checkbox" v-model="todo.completed" @change="toggleCompleted"> <span :class="{ 'completed': todo.completed }">{{ todo.text }}</span> <button @click="$emit('remove')">删除</button> </div> </template> <script> export default { props: ['todo'], methods: { toggleCompleted() { this.$emit('toggle', this.todo.id); } } } </script> <style> .completed { text-decoration: line-through; } </style> ``` 在这个组件中,我们有一个单选框来标记待办事项是否已经完成,如果待办事项已经完成,它的文本将会有删除线。我们还有一个删除按钮来删除待办事项。 3. 创建一个待办事项列表组件 接下来,我们要创建一个待办事项列表组件,它将会用来显示所有的待办事项。在项目根目录下的 `src/components` 中创建一个新的文件 `TodoList.vue`: ```html <template> <div class="todo-list"> <div v-for="todo in filteredTodos" :key="todo.id"> <TodoItem :todo="todo" @toggle="toggleTodo" @remove="removeTodo"></TodoItem> </div> </div> </template> <script> import TodoItem from './TodoItem.vue'; export default { components: { TodoItem }, props: ['todos'], computed: { filteredTodos() { return this.todos.filter(todo => { return !this.showCompleted || todo.completed === false; }); } }, data() { return { showCompleted: false }; }, methods: { toggleTodo(id) { const todo = this.todos.find(todo => todo.id === id); todo.completed = !todo.completed; }, removeTodo() { this.$emit('remove'); } } } </script> <style> .todo-list { margin-top: 20px; } </style> ``` 在这个组件中,我们使用了 `v-for` 指令来循环渲染每一个待办事项。我们还引入了之前创建的待办事项组件 `TodoItem`。我们还有一个切换已完成待办事项的开关。 4. 创建一个添加待办事项的组件 现在,我们要创建一个添加待办事项的组件。在项目根目录下的 `src/components` 中创建一个新的文件 `AddTodo.vue`: ```html <template> <div class="add-todo"> <input type="text" v-model="newTodo" placeholder="添加新的待办事项"> <button @click="addTodo">添加</button> </div> </template> <script> export default { data() { return { newTodo: '' }; }, methods: { addTodo() { if (this.newTodo) { this.$emit('add', this.newTodo); this.newTodo = ''; } } } } </script> <style> .add-todo { margin-top: 20px; } </style> ``` 在这个组件中,我们有一个文本输入框和一个添加按钮。当用户点击添加按钮时,我们将会触发一个事件来添加新的待办事项。 5. 创建一个根组件 最后,我们要创建一个根组件,它将会包含所有的子组件,并且处理待办事项的数据和状态。在项目根目录下的 `src` 中创建一个新的文件 `App.vue`: ```html <template> <div class="app"> <h1>待办事项</h1> <AddTodo @add="addTodo"></AddTodo> <div v-if="todos.length"> <TodoList :todos="todos" @remove="removeTodo"></TodoList> <div> <label> <input type="checkbox" v-model="showCompleted"> 显示已完成 </label> </div> </div> <div v-else> 没有待办事项 </div> </div> </template> <script> import TodoList from './components/TodoList.vue'; import AddTodo from './components/AddTodo.vue'; export default { components: { TodoList, AddTodo }, data() { return { todos: [], showCompleted: false, nextId: 1 }; }, methods: { addTodo:text=> { this.todos.push({ id: this.nextId++, text, completed: false }); }, removeTodo() { this.todos = this.todos.filter(todo => !todo.completed); } } } </script> <style> .app { max-width: 600px; margin: 0 auto; padding: 20px; font-family: 'Arial'; } </style> ``` 在这个组件中,我们引入了之前创建的添加待办事项组件和待办事项列表组件。我们还有一个 `data` 对象来存储待办事项的数据和状态。我们还有一些方法来添加、删除和切换待办事项的状态。 6. 添加路由 最后,我们要添加路由来让用户能够访问我们的待办事项应用。在项目根目录下的 `src` 中创建一个新的文件 `router.js`: ```js import Vue from 'vue'; import VueRouter from 'vue-router'; import App from './App.vue'; Vue.use(VueRouter); const routes = [ { path: '/', name: 'home', component: App } ]; const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }); export default router; ``` 在这个文件中,我们首先引入了 VueVue Router,并使用 Vue.use 注册 Vue Router。我们还定义了一个路由对象,它将会指向我们的根组件。最后,我们创建了一个 VueRouter 实例,并把路由对象传递进去。 7. 启动应用 到这里,我们的待办事项应用已经完成了。现在,我们可以在命令行中运行以下命令启动应用: ``` npm run serve ``` 应用将会运行在 http://localhost:8080 上,你现在可以在浏览器中访问它了。如果你想要构建一个生产环境的应用,可以运行以下命令: ``` npm run build ``` 这个命令将会生成一个可以部署的静态文件,你可以将它部署到任何能够托管静态文件的地方。 以上是一个简单的待办事项应用的实现过程,它涉及到了 Vue 数据绑定、组件、路由等技术。当然,这只是一个简单的例子,你可以根据自己的需要添加更多的功能和交互效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 如何解决vuex页面刷新数据丢失问题? 7555
  • 前端如何根据不同用户做权限控制? 3949
  • vue 从入门到精通之【vue数据视图】(一) 1190
  • vue 从入门到精通之【数据操作(data,methods,computed,watch)+filter】(二) 655
  • vue从入门到精通之【vue-router】(八) 564

分类专栏

  • vue 10篇
  • 前端 11篇
  • JAVA 1篇
  • 工作流 1篇
  • 数据库 1篇

最新评论

  • 前端如何根据不同用户做权限控制?

    qq_43362188: 角色的权限控制比较容易,问题是有时候需要控制的是人员(即不同账号)的权限,这个怎么去控制

大家在看

  • 数据分析工具|数据分析利器与业务决策的好帮手vividiem Desktop
  • Modbus.SlaveException
  • 2024年网络安全学习指南!详尽路线图,从零基础到黑客高手的进阶之路! 475
  • 历年CSP-J初赛真题解析 | 2013年CSP-J初赛选择题(1-22)
  • 数据结构--栈和队列(详解+代码实现

最新文章

  • 如何解决vuex页面刷新数据丢失问题?
  • vue从入门到精通之【vue-router】(八)
  • 前端如何根据不同用户做权限控制?
2022年11篇
2019年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

聚圣源画笔素材五开起名字符文工房2宝宝周易取名起名大全使用父母的的名字给孩子起名序列玩家女生起名 贾姓杨潇唐沐雪的小说免费阅读公司起名大全大师百合婚恋网给宝宝取名起名大全姓马注册公司怎么起名字最时尚的qq签名一之味炒南瓜给的林姓的男孩起名和讯财经日历香油商标起名字得过且过意思机战l隐藏女属龙起名免费周易起名网公司起名凶吉能查柔软的肉体东西湖职校我就是这般女子电视剧全集免费观看空心砖墙国际公司起名苏州市安全教育平台属马起名的宜用字,忌用字淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化