Vue入门基础篇

写在前面:Vue API 文档

一、创建实例

var data = {
	foo:'bar'
}

var vm = new Vue({
	el:'#app',
	data:data
	})

如果在后续的操作中,无论是对vue实例的属性值做修改还是对原始data数据的值做修改,有联动效果,除非在创建data对象之后将其冻结。

Object.freeze(data)

除了数据属性外,Vue 实例还暴露出了一些有用的实例与方法,都使用 $ 做前缀,具体查看 API 文档

二、实例生命周期钩子

其实就是重写在实例生命周期的各个阶段时的方法,例如created、updated、destroyed、beforeDestory.
具体参考 api 文档

三、模板语法

1、插值

文本
<span>Message:{{ msg }}</span>

文本插值会随着对象上属性的改变而改变。可以通过 v-once 指令执行一次性插值。

<span v-once>这个值将不会改变:{{ msg }}</span>
原始 HTML

使用 v-html 指令,示例:

<p>Using mustaches: {{ rawHtml }}</p>
<!-- 下面是使用 v-html指令的元素,将会显示渲染过后的 html -->
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
特性

Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:

<div v-bind:id="dynamicId"></div>

布尔特性的情况下,dynamicId存在即暗示为 true

使用 javascript 表达式

如下使用示例:

{{ number + 1 }}
{{ ok? 'YES':'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list' + 'id'"></div>

2、指令

指令是指带有 v- 前缀的的特殊特性。其预期值是单个 Javascript 表达式( v-for 除外 )

参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。如:

<a v-bind:href="url">...</a>

在这里 href 是参数,告知 v-bind 指令将该元素的 href 特性与表达式 url 的值绑定

修饰符

修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。如:

<form v-on:submit.prevent="onSubmit">...</form>

.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

3、缩写

v-bind 缩写 (?

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

<!-- 缩写 -->
<a :href="url">...</a>

v-on 缩写 (@)

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

<!-- 缩写 -->
<a @click="doSomething">...</a>

四、侦听器

通过 watch 提供,用来响应数据的变化。当需要数据变化时执行异步活开销较大的操作时,尤为有用。

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
	var 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, oldQuestion) {
	      this.answer = 'Waiting for you to stop typing...'
	      this.debouncedGetAnswer()
	    }
	  },
	  created: function () {
	    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
	    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
	    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
	    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
	    // 请参考:https://lodash.com/docs#debounce
	    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
	  },
	  methods: {
	    getAnswer: function () {
	      if (this.question.indexOf('?') === -1) {
	        this.answer = 'Questions usually contain a question mark. ;-)'
	        return
	      }
	      this.answer = 'Thinking...'
	      var vm = this
	      axios.get('https://yesno.wtf/api')
	        .then(function (response) {
	          vm.answer = _.capitalize(response.data.answer)
	        })
	        .catch(function (error) {
	          vm.answer = 'Error! Could not reach the API. ' + error
	        })
	    }
	  }
	})
</script>

除了 watch 选项之外,您还可以使用命令式的 vm.$watch API

五、计算属性和侦听器

1、计算属性 computed

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

<script>
	var vm = new Vue({
	  el: '#example',
	  data: {
	    message: 'Hello'
	  },
	  // 定义计算属性
	  computed: {
	    reversedMessage: function () {
	      return this.message.split('').reverse().join('')
	    }
	  }
	})
</script>

因为计算属性 reversedMessage 是依赖 message 属性的,所以如果对 message 属性更改,计算属性 reversedMessage 的值也会改变。

2、计算属性 VS 方法

可以通过定义函数来代替计算属性,但是函数会在每次调用时都执行,而计算属性会基于其依赖进行缓存,每次从缓存读取,只有在依赖发生改变时才会重新执行并进行缓存。

3、计算属性 VS 侦听属性

侦听属性:用来侦听每个属性的变动,以做出相应操作。应该适时使用,在如下示例中,明显使用计算属性更加简洁合理:
html:

<div id="demo">{{ fullName }}</div>

使用侦听属性:

<script>
	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
	    }
	  }
	})
<script>

其同时侦听了 firstName 和 lastName ,任一改变fullName 都会改变,但是,请看计算属性:

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

4、计算属性的 setter

计算属性默认的只有 getter ,不过也可以在需要时提供一个 setter 。

<script>
	var vm = new Vue({
		el: '#demo',
		data: {
		  firstName: 'Foo',
		  lastName: 'Bar'
		},
		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]
		    }
		  }
		}
</script>

六、Class 与 Style 绑定

1、绑定 HTML Class

对象语法:
<div class="static" v-bind:class="{ active: isActive }">
	...
</div>

如上例,给 div 绑定了一个 active 的 class,可以通过在 vue data 中改变值 isActive 的值(True | False)来控制是否有 active class。渲染结果:

<!-- 若 isActive 为 True -->
<div class="static active">
	...
</div>

<!-- 若 isActive 为 False -->
<div class="static">
	...
</div>

也可对绑定 class 为一个 data 对象:

<div v-bind:class="classObject"></div>
...
	data: {
	  classObject: {
	    active: true,
	    'text-danger': false
	  }
	}
...

当然,也可以 class 绑定一个计算属性:

<div v-bind:class="classObject"></div>

...
	data: {
	  isActive: true,
	  error: null
	},
	computed: {
	  classObject: function () {
	    return {
	      active: this.isActive && !this.error,
	      'text-danger': this.error && this.error.type === 'fatal'
	    }
	  }
	}
...
数组语法

同样,也可以给 v-bind:class 绑定一个数组,以应用一个 class 列表:

<div v-bind:class="[activeClass, errorClass]"></div>
...
	data: {
	  activeClass: 'active',
	  errorClass: 'text-danger'
	}
...

将会渲染为:

<div class="active text-danger"></div>

数组语法中也可以使用对象语法:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
用在组件上

当在一个自定义组件上使用 class 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。

<!-- 定义组件 -->
Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})
<!-- 使用组件时 -->
<my-component class="baz boo"></my-component>

最终将会被渲染为:

<p class="foo bar baz boo">Hi</p>

对于带数据绑定 class 也同样适用:

<my-component v-bind:class="{ active: isActive }"></my-component>

当 isActive 为 truthy 时,HTML 将被渲染成为:

<p class="foo bar active">Hi</p>

2、绑定内联样式(Style)

对象语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。

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

当然,也可以直接绑定一个 js 对象:

<div v-bind:style="styleObject"></div>
...
	data: {
	  styleObject: {
	    color: 'red',
	    fontSize: '13px'
	  }
	}
...
数组语法

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

<div v-bind:style="[baseStyles, overridingStyles]"></div>
自动添加前缀

当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。

多重值

从 2.3.0 起你可以为 style 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。

七、条件渲染

1、v-if 、v-else-if 、v-else:

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

2、用 key 来管理可复用的元素

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

当这样使用时。在两个 template 之间切换时会带着已经在 input 中的输入值,但是有时候不总符合实际需求,所以 Vue 提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key 属性即可:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

3、v-show

带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display.

<h1 v-show="ok">Hello!</h1>

注意:v-show 不支持 <template> 元素,也不支持 v-else

4、v-if VS v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

4、v-if VS v-for 一起使用

不推荐将 v-if VS v-for 一起使用,可查看 风格指南

八、列表渲染

最简单的示例:

<ul id="example-1">
  <li v-for="item in items">  <!-- 也可以使用of代替in,如:v-for="item of items" -->
    {{ item.message }}
  </li>
</ul>
...
	var example1 = new Vue({
	  el: '#example-1',
	  data: {
	    items: [
	      { message: 'Foo' },
	      { message: 'Bar' }
	    ]
	  }
	})
...

在 v-for 块中,我们拥有对父作用域属性的完全访问权限。v-for 还支持一个可选的第二个参数为当前项的索引。

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
...
	var example2 = new Vue({
	  el: '#example-2',
	  data: {
	    parentMessage: 'Parent',
	    items: [
	      { message: 'Foo' },
	      { message: 'Bar' }
	    ]
	  }
	})
...

1、对象的 v-for

可以通过 v-for 来遍历对象,其提供了三个参数(value,key,index)

<div v-for="(value, key, index) in object">   <!-- 也可以为 value 或 (value,key) -->
  {{ index }}. {{ key }}: {{ value }}
</div>
...
	new Vue({
	  el: '#v-for-object',
	  data: {
	    object: {
	      firstName: 'John',
	      lastName: 'Doe',
	      age: 30
	    }
	  }
	})
...

2、为 v-for 设置一个 key

当用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略,简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。

但是,在很多情况下,为了跟踪节点,需要为每一个节点提供一个唯一的 key 属性。(使用 v-bind )

<div v-for="item in items" :key="item.id">
	<!-- :key 为 v-bind:key 的缩写 -->
	<!-- 内容 -->
</div>

3、数组的更新检测

数组的变异方法

Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
替换数组

变异方法 会改变其调用的原始数据。与其对应的为非变异方法,如filter()、concat()、slice(),他们不会改变原始数据,通常会返回一个新的数组。我们可以用新的数组来替换旧的数组。

...
	example1.items = example1.items.filter(function (item) {
	  return item.message.match(/Foo/)
	})
...

当我们使用含有相同元素的数组去替换一个新的数组时,Vue 很流弊的并不会丢弃现有的 DOM 重新渲染整个列表。

注意事项:

Vue 无法坚持数组的一下变动:

  • 使用索引直接设置一个项时,如:vm.items[indexOfItem] = newValue
  • 修改数组的长度时,如:vm.items.length = newLength

举个栗子:

<script>
	...
	var vm = new Vue({
	  data: {
	    items: ['a', 'b', 'c']
	  }
	})
	vm.items[1] = 'x'    // 不是响应性的
	vm.items.length = 2  // 不是响应性的
	...
</script>

为了解决第一类问题,可以使用以下两种方式:(响应式的更改值)

<script>
	...
	// Vue.set
	Vue.set(vm.items, indexOfItem, newValue)
	<!-- 
	全局方法 Vue.set 在每一vue实例中都有一个别名:vm.$set
	也可以直接使用:vm.$set(vm.items, indexOfItem, newValue)
	 -->
	 
	// Array.prototype.splice
	vm.items.splice(indexOfItem, 1, newValue)
	...
</script>

为了解决第二类问题,也可以使用 splice:

<script>
	...
	vm.items.splice(newLength)
	...
</script>

4、对象更改检测注意事项

同样的,由于 js 的限制,vue 不能直接对 对象属性 进行添加或者删除(其不是响应式的)。需要借助全局方法 Vue.set(object,key,value).

<script>
	var vm = new Vue({
	  data: {
	    userProfile: {
	      name: 'Anika'
	    }
	  }
	})
	// 如果要添加新的属性
	Vue.set(vm.userProfile, 'age', 27)
	// Vue.set() 为全局方法,在 vue 示例中有一个别名:vm.$set()
	vm.$set(vm.userProfile, 'age', 27)
</script>

如果要对已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。这种情况下,可以用两个对象属性创建一个新的对象,应该这样:

	...
	vm.userProfile = Object.assign({}, vm.userProfile, {
	  age: 27,
	  favoriteColor: 'Vue Green'
	})
	...

错误示例:

	...
	Object.assign(vm.userProfile, {
	  age: 27,
	  favoriteColor: 'Vue Green'
	})
	...

4、显示过滤或者排序结果

通过创建返回过滤或者排序数组的计算属性来实现:
示例:

	...
	<li v-for="n in evenNumbers">{{ n }}</li>
	...
	// javascript
	data: {
	  numbers: [ 1, 2, 3, 4, 5 ]
	},
	computed: {
	  evenNumbers: function () {
	    return this.numbers.filter(function (number) {
	      return number % 2 === 0
	    })
	  }
	}
	...

当在计算属性不适用的情况下(例如计算属性不可以在v-for中使用),可以通过定 methods 来实现:

	...
	<li v-for="n in even(numbers)">{{ n }}</li>
	...
	
	data: {
	  numbers: [ 1, 2, 3, 4, 5 ]
	},
	methods: {
	  even: function (numbers) {
	    return numbers.filter(function (number) {
	      return number % 2 === 0
	    })
	  }
	}
	...

5、一段取值范围的 v-for

在 v-for 中也可以取整,例如:

	<div>
		<span v-for="n in 10">
			{{ n }}
		</span>
	</div>

结果: 1 2 3 4 5 6 7 8 9 10

6、在 template 中使用 v-for

	<ul>
	  <template v-for="item in items">
	    <li>{{ item.msg }}</li>
	    <li class="divider" role="presentation"></li>
	  </template>
	</ul>

7、v-for 和 v-if

当 v-for 和 v-if 处于同一个节点中时,v-for 拥有更高的优先级。即:会先执行 v-for,v-if 会贼每一次循环中生效。

	<li v-for="todo in todos" v-if="!todo.isComplete">
	  {{ todo }}
	</li>

8、组件的 v-for

在组件中可以像在普通元素中一样使用 v-for:

<my-component v-for="item in items" :key="item.id"></my-component>

但是任何的数据都不会被传递到组件中(组件有自己独立的作用域)。要讲迭代的数据传递到组件中,需要使用 props:

	<my-component
		v-for="(item, index) in items"
		v-bind:item="item"
		v-bind:index="index"
		v-bind:key="item.id"
	></my-component>

**注意:**在 Vue 2.2.0 + 的版本中,在组件中使用 v-for 时,必须绑定 key

为什么不自动的把 item 注入到组件中?

明确组件数据的来源能够使组件在其他场合重复使用。如果自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合

9、一个 todo-list 的完整例子

Vue 文档 中查看效果

html:

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>

javascript:

<script>
	Vue.component('todo-item', {
	  template: '\
	    <li>\
	      {{ title }}\
	      <button v-on:click="$emit(\'remove\')">Remove</button>\
	    </li>\
	  ',
	  props: ['title']
	})

	new Vue({
	  el: '#todo-list-example',
	  data: {
	    newTodoText: '',
	    todos: [
	      {
	        id: 1,
	        title: 'Do the dishes',
	      },
	      {
	        id: 2,
	        title: 'Take out the trash',
	      },
	      {
	        id: 3,
	        title: 'Mow the lawn'
	      }
	    ],
	    nextTodoId: 4
	  },
	  methods: {
	    addNewTodo: function () {
	      this.todos.push({
	        id: this.nextTodoId++,
	        title: this.newTodoText
	      })
	      this.newTodoText = ''
	    }
	  }
	})
</script>

九、事件处理

1、监听事件

使用 v-on 指令来监听 DOM 事件,并在触发是执行一段 js 代码。
示例:

	<div id="example-1">
		<button v-on:click="counter += 1">Add 1</button>
		<p>The button above has been clicked {{ counter }} times.</p>
	</div>
	
	...
	var example1 = new Vue({
	  el: '#example-1',
	  data: {
	    counter: 0
	  }
	})
	...

2、事件处理方法

当事件处理比较复杂时,直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。

	<div id="example-2">
		<!-- `greet` 是在下面定义的方法名 -->
		<button v-on:click="greet">Greet</button>
	</div>
	
	...
	
	var example2 = new Vue({
	  el: '#example-2',
	  data: {
	    name: 'Vue.js'
	  },
	  // 在 `methods` 对象中定义方法
	  methods: {
	    greet: function (event) {
	      // `this` 在方法里指向当前 Vue 实例
	      alert('Hello ' + this.name + '!')
	      // `event` 是原生 DOM 事件
	      if (event) {
	        alert(event.target.tagName)
	      }
	    }
	  }
	})
	
	// 也可以用 JavaScript 直接调用方法
	example2.greet() // => 'Hello Vue.js!'
	...

3、内联处理器中的方法

除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:

	<div id="example-3">
		<button v-on:click="say('hi')">Say hi</button>
		<button v-on:click="say('what')">Say what</button>
	</div>
	
	...
	new Vue({
	  el: '#example-3',
	  methods: {
	    say: function (message) {
	      alert(message)
	    }
	  }
	})
	...

当需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

	...
	<button v-on:click="warn('Form cannot be submitted yet.', $event)">
		Submit
	</button>
	...
	methods: {
	  warn: function (message, event) {
	    // 现在我们可以访问原生事件对象
	    if (event) event.preventDefault()
	    alert(message)
	  }
	}
	...

4、事件修饰符

Vue.js 为 v-on 提供了事件修饰符,由点开头的指令后缀表示。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

示例:

	<!-- 阻止单击事件继续传播 -->
	<a v-on:click.stop="doThis"></a>
	
	<!-- 提交事件不再重载页面 -->
	<form v-on:submit.prevent="onSubmit"></form>
	
	<!-- 修饰符可以串联 -->
	<a v-on:click.stop.prevent="doThat"></a>
	
	<!-- 只有修饰符 -->
	<form v-on:submit.prevent></form>
	
	<!-- 添加事件监听器时使用事件捕获模式 -->
	<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
	<div v-on:click.capture="doThis">...</div>
	
	<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
	<!-- 即事件不是从内部元素触发的 -->
	<div v-on:click.self="doThat">...</div>
	
	<!-- 点击事件将只会触发一次(2.1.4 中新增) -->
	<a v-on:click.once="doThis"></a>
	
	<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
	<!-- 而不会等待 `onScroll` 完成  -->
	<!-- 这其中包含 `event.preventDefault()` 的情况 -->
	<div v-on:scroll.passive="onScroll">...</div>
	<!--
	不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,并且浏览器会告诉你不要阻止事件的默认行为。
	-->

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。
因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击

5、按键修饰符

使用 v-on 在监听键盘事件时添加按键修饰符:

	<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
	<input v-on:keyup.13="submit">
	
	<!-- 同上,enter 为 Vue 为 keyCode == 13 提供的别名 -->
	<input v-on:keyup.enter="submit">

Vue 提供的按键别名:

  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

另外,可以通过全局变量 config.keyCodes 自定义按键别名:

Vue.keyCodes.f1 = 112
自动提配按键修饰符

在 Vue 2.5.0 中新增

PS: 有一些按键 (.esc 以及所有的方向键) 在 IE9 中有不同的 key 值, 如果你想支持 IE9,它们的内置别名应该是首选

直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符:

	<input @keyup.page-down="onPageDown">

6、系统修饰符

Vue 2.1.0 新增

可以使用如下修饰符来实现“仅在按下相应按键时才触发鼠标 或 键盘事件监听器”

  • .ctrl
  • .alt
  • .shift
  • .meta //在 mac 中为 command,在 windows 中为 win。

示例:

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
.exact 修饰符

Vue 2.5.0 新增

.exact 修饰符允许控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
鼠标按键修饰符

Vue 2.2.0 新增

这些修饰符会限制处理函数仅响应特定的鼠标按钮

  • .left
  • .right
  • .middle

十、表单输入绑定

1、基础用法

可以使用 v-model 指令在表单的 <input>、<textarea>、<select> 元素上创建双向的数据绑定。

v-model 会忽略 表单元素的 value、checked、selected 特性的初始值。它只认 Vue 实例中的数据来源。

v-model 不会再输入法组合文字的过程中更改值。要处理这个过程,需要使用 input 事件。

常见表单元素用法
<!-- 文本框 -->
<input v-model="message" placeholder="edit me">

<!-- 多行文本 -->
<textarea v-model="message" placeholder="add multiple lines"></textarea>

<!-- 复选框 -->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

<!-- 多个复选框绑定到同一个数组 -->
<div id='example-3'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>

<!-- 单选按钮 -->
<div id="example-4">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>

<!-- 选择框 单选 -->
<div id="example-5">
  <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

<!-- 选择框 多选 -->
<div id="example-6">
  <select v-model="selected" multiple style="width: 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

<!-- 动态渲染 -->
<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>
...
new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})
...

2、值绑定

对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串。

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">

<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>
复选框 - 绑定值
<!-- 将 true 绑定为 yes,false 绑定为 no -->
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
单选按钮 - 绑定值
<input type="radio" v-model="pick" v-bind:value="a">

// 当选中时
vm.pick === vm.a
选择框的选项
<select v-model="selected">
    <!-- 内联对象字面量 -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>

// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123

3、修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步,可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number

自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

(因为即使在 type=“number” 时,HTML 输入元素的值也总会返回字符串。)

<input v-model.number="age" type="number">
.trim

自动过滤用户输入的首尾空白字符:

<input v-model.trim="msg">

关于组建相关的更多功能请查看后续文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值