Vue初探

疑问点

  • 之前开始学习Vue时,老是搞不清楚为什么有的时候是:
    v-bind:class="dynamicClass"
    而有的时候是:v-bind:class="{active: isActive}",其实是v-bind可以绑定变量、对象或数组
  • 使用v-model可以实现双向绑定; 如用在表单控件元素上实现双向绑定,也就是说我们在表单控件上输入数据,可以实时的反应到Vue实例的data上,在data上的数据改变也可以体现在表单控件元素上。
    v-model文档
    注意:双向绑定在富表单的页面上很有用,但是双向绑定不利于我们对数据的掌控

Vue实例

语法:var vm = new Vue({});
说明:通过new Vue来实例化一个Vue对象,在实例化时,可以传入:数据、模板、挂载元素、方法、生命周期钩子等选项

**注意:

  • **Vue实例必须要绑定一个元素上,这个Vue实例就是为它绑定的元素服务的,它们之间建立联系,元素的变化可以通过该实例来获取,同时,通过该实例,也可以操作这个元素,实例中数据的变化可以体现在该元素上
  • 当创建一个Vue实例时,如果data属性上的数据暂时不需要使用,那么也必须先添加到data上,如果在之后添加,则无效;因为Vue会在创造实例时,找到data属性上的所有数据,并将其注册到Vue的响应式系统中,所以必须在创建Vue的实例时,将data上的所有数据都添加上去。
    如:
// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
  data: data
})
// 对data中a的更改会体现在vm的data中
vm.a === data.a    // true
data.a = 2;        // 会导致 vm.a = 2
vm.a =3            // 会导致data.a = 3

vm.b = 4            // 这样是无效的,b并不能被添加到vm实例中
console.log(vm.b);   // 输出 undefined

// 如果知道b会在将来使用,那么必须在创建vm实例时添加,如下:
var vm = new Vue({
  data: {
      a: 1,
      b: ''         // 将b设置为空即可
  }
})

参考: Vue数据与方法

模板语法

插值

原始HTML

通过v-html可以将html代码插入到页面中
如:

<div id="app">
  <div v-html="rawhtml"></div>
  <div>{{msg}}</div>
</div>

var vm = new Vue({
   el: "#app",
   data: {
      rawhtml: "<a href='www.baidu.com'>baidu</a>",
      msg: "<a href='www.baidu.com'>baidu</a>"
   }
});

上面代码实际输出如下:

v-html演示

说明:通过v-html可以将rawhtml作为原始html替换掉当前的div,而使用{{}},则表示将msg作为文本插入到所在的位置
注意: 动态的渲染html是非常危险的,很可能导致XSS攻击

特性

mustache语法不能用在html的特性上,需要使用v-bind指令来绑定特性,如:
<div v-bind:class="dynamicClass"></div>
注意:dynamicClass是一个变量

缩写

  • v-bind缩写
    如: <div v-bind:id="dynamicId"></div>
    缩写为:<div :id="dynamicId"><div>
    也就是说使用:来代替v-bind:

  • v-on缩写
    如:<button v-on:click="reverse"></button>
    缩写为:<button @click="reverse"></button>
    也就是使用 @来对v-on进行缩写

实例属性

通过 $可以访问到实例属性

var data = {a: 1};
var app  = new Vue({
   el: "#app",
   data: data
});
app.$data === app.data    // true
app.$el === document.getElementById('app');

// 还有一些实例方法
app.$watch('a', function(newValue, oldValue) {
   // 该回调函数会在a被改变后调用
});

实例生命周期

var vm = new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vm 实例
    console.log('a is: ' + this.a)
  }
})

created方法会在实例被创建时被调用

绑定数据到HTML的特性上

可以通过v-bind:来绑定变量到HTML的特性上
注意:一般来说,HTML的特性(如:id、class、style等,其实就是html的属性)接收的是字符串,而如果我们需要绑定一个变量到HTML的特性上,那么就需要使用v-bind:来操作

如:

// id 
<p v-bind:id="dynamicId"></p>  
// class
<p v-bind:class="dynamicClass"></p>

注意:上面代码中的dynamicIddynamicClass都是变量

使用JS的表达式

上面说的是绑定简单的属性到HTML的特性上,同时,还可以使用JS表达式来绑定数据
注意:使用表达式时,只支持单个表达式

// 表达式里面的id是变量
<div v-bind:id="'list-' + id"> </div>

类似于下面的语句不会生效

<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

指令

指令是带有v-前缀的特殊属性,指令属性的值预期是单个JS表达式v-for指令例外)
指令的职责:指令的值改变时,将其产生的连带影响,响应式的作用于DOM中
如:

// 如果seen表达式为真,则插入文本,为假则不插入
<p v-if="seen">现在你看到我了</p>

v-on指令
通过v-on指令可以来指定监听事件

// 监听click事件
<button v-on:click="dosome"></button> 

在监听的事件之后,还可以添加修饰词,例如有时候,我们需要阻止事件的默认行为

// 通过添加prevent修饰符, 提交事件不再重载页面 
<a v-on:click.prevent="doSomething">

缩写

v-bind缩写

<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>

v-on缩写

<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>

计算属性

计算属性其实就是在Vue实例的computed属性上定义的一些函数;
如:

computed: {
  now: function () {
    return Date.now()
  }
}

我们知道可以通过在Vue实例的 methods属性上定义函数,这两者产生的结果是相同的,那么这两者有什么区别呢?

注意:这里定义了一个计算属性now,并为其添加了函数,其本质就是将该函数用作now属性的getter函数,当访问now时,就调用该函数

计算属性computed和methods的区别
其最主要的区别在于:当它们进行计算求值时,如果依赖的数据没有发生改变,它们两者会进行不同的操作,computed是基于它的依赖进行缓存的,只有在依赖的数据发生改变时,才进行重新求值;而对于methods则不管依赖的数据有没有发生改变,只要调用方法,就会重新求值,进行渲染;

注意:计算属性只有getter,如果需要设置值,那么就要自己实现setter,如下:

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

观察watch

观察属性可以让我们对某些数据进行观测,当数据发生变化时,就执行相应的函数,这在异步获取数据时,很有用;
如下:

ar watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 question 发生改变,这个函数就会运行
    question: function (newQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },
}

上面代码中,当question发生变化时,就会执行后面的函数

通过v-bind绑定class与style

绑定class

对象语法

// 表示如果isActive变量为true,则添加active类, 如果为false,则不添加
<p v-bind:class="{active: isActive}"></p>

当然,还可以添加多个:

<div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>

// Vue实例中的数据
data: {
  isActive: true,
  hasError: false
}

利用计算属性(很实用的绑定class的方式)

<div :class="classObj">数据</div>

var wm = new Vue({
  data: {
     isActive: false,
     error: null
  },
  computed: {
     classObj: function() {
       // 返回的是一个对象
       // 该计算属性依赖于isActive和error,因此,当需要更改时,只要更改isActive和error即可
        return {  
           active: this.isActive && !this.error
           'text-danger': this. error && this.error.type === 'fatal'
        }
     }
  }
});

数组语法
还可以传递一个数组

<div v-bind:class="[activeClass, errorClass]">
// Vue实例中的data
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}
// 渲染后的结果
<div class="active text-danger"></div>

还可以使用三元运算符:

<div v-bind:class="[isActive ? activeClass : '', errorClass]">
//此例始终添加 errorClass ,但是只有在 isActive 是 true 时添加 activeClass

// 上面的语法可以改写为:
<div v-bind:class="[{ active: isActive }, errorClass]">

绑定内联样式

对象语法

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

// Vue实例中的data
data: {
  activeColor: 'red',
  fontSize: 30
}

通常,直接绑定一个样式对象更好

<div v-bind:style="styleObject"></div>

// Vue实例中的data
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

数组语法
v-bind:style 的数组语法可以将多个样式对象应用到一个元素上:

<div v-bind:style="[baseStyles, overridingStyles]">

条件渲染

v-show

带有v-show指令的元素一直在DOM树中,v-show只是简单的切换css的display: nonedisplay: block

注意v-show不支持<template>语法,同时,也不支持v-else

v-if VS v-show

v-if: 是真正的条件渲染,因为它会确保在切换的过程中条件块内的事件监听器和子组件适当的被销毁或重建
v-if也是惰性的:因为如果在初始化渲染时条件不成立, 那么就什么也不会做,直到条件为真时,才会被渲染到页面上
v-show则不同,不管条件是否为真都会被渲染到页面上,它只是简单的进行display的切换

v-if有更高的切换开销,而v-show则有更高的初始渲染开销,因此如果需要频繁的切换,则使用v-show更合适;如果在运行时不需要经常切换,则使用v-if更好

注意:v-ifv-show同时使用时,v-show的优先级更高

数组更新检测

变异方法

调用这些方法时,将会导致视图更新,方法如下:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverser()

变异方法会改变原始数组

非变异方法

非变异方法不会改变原数组,它们会返回一个新的数组

  • slice()
  • filter()
  • concat()

注意事项

对数组的更改

Vue不能检测以下变动的数组:

  1. 当利用索引值直接设置一个项时,如:vm.items[index] = newValue
  2. 当修改数组的长度时,如:vm.items.length = newLength
    当使用上面两种方式设置数组时,Vue将无法检测到,也就是说,如果在视图上不会进行相应的更新,如下:
<div id="app-11">
    <li v-for="(item, index) in objects">
       {{index}} - {{item.todo}}
    </li>
</div>

// js
var app11 = new Vue({
  el: "#app-11",
  data: {
    objects: [
      {todo: 'a'},
      {todo: 'b'},
      {todo: 'c'}
    ]
  }
});

// 如果如下更改,则不会生效
app11.objects[0] = {todo: 'change'}      // Vue将无法检测到该变动,视图不会更新

// 使用以下方式,则会生效
// 方法一:使用Vue.set
Vue.set(app11.objects, 0, {todo: 'change'});
// 方法二:使用splice
app11.objects.splice(0, 1, {todo: 'change'});

// 如果需要改变数组长度,则可以使用如下方式:
app11.objects.splice(5);    // 表示将长度修改为5

总结:

  • 当需要利用索引设置数组中对应的一个项时,可以使用以下两种方式:
    方法一:Vue.set(example.items, indexofItem, newItem)
    方法二:example.items.splice(indexofItem, 1, newItem)
  • 如果需要修改数组的长度,可以使用如下方法:
    example.items.splice(newLength)

参考:列表渲染

对对象的更改

与数组类似,Vue也无法检测到对象属性的添加和删除

测试代码

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

推荐阅读更多精彩内容