Vue 2.x教程之基础API


Posted in Javascript onMarch 06, 2017

本文主要介绍的是关于Vue 2.x之基础API的相关内容,主要内容如下

  • 模板语法(文本插值、属性绑定、JS表达式、过滤器、指令)
  • Vue实例(viewModal(属性+函数)、生命周期)
  • 计算属性和监听器 (computed(get,set) 与 watch)
  • 样式绑定(对象绑定、数组绑定、内联绑定)
  • 条件绑定(v-if v-show)
  • 列表渲染 (v-for、:key、数组监测、过滤/排序)
  • 事件处理 (监听、修饰符、key修饰符)
  • 表单输入绑定(text、checkbox、radio、select)

一、模板语法

文本插值

- 使用 `{{ }} / <span v-text="msg"></span>` 绑定数据
- `{{ }}` 纯文本绑定,单向,随vm变化而变化
- `<span v-once>{{ msg }}</span>` 纯文本,单次,不跟随vm变化
- `<span v-html="msg"></span>` 不转义html标签,绑定html

属性绑定

- 使用 `v-bind` 指令绑定数据至标签属性
- `<a v-bind:id="msgId"></a> 简写 <a :id="msgId"></a>`

模板中的JS

  • 支持表达式执行,但不支持多个表达式、语句和控制流的执行
  • 属性绑定和绑定的数据都支持JS表达式
//加减乘除、三元运算、方法调用
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
//错误用法
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

过滤器

- 使用 `|` 对原始值进行处理
- 用于属性绑定与 `{{ }}`
- `{{ msg | capitalize }} <a :id="msgId | formatId"></a>`
- 可以串联 `{{ msg | filterA | filterB }}`
- 可以接收参数 `{{ msg | filterA(arg1, arg2) }}`

指令

- 带有 `v-` 前缀的特殊属性
- 当其表达式的值改变时相应地将某些行为应用到 DOM 上
- `v-bind/v-for/v-html/v-on/v-if/...`
- `v-bind` 缩写 `<a v-bind:href="url" rel="external nofollow" rel="external nofollow" ></a><a :href="url" rel="external nofollow" rel="external nofollow" ></a>`
- `v-on` 缩写 `<a v-on:click="doSomething"></a><a @click="doSomething"></a>`

注册过滤器

//全局注册
Vue.filters('capitalize',value=>{
 if (!value) return ''
 value = value.toString()
 return value.charAt(0).toUpperCase() + value.slice(1)
})
//局部注册
filters: {
 capitalize: function (value, arg1) {
 if (!value) return ''
 value = value.toString()
 return value.charAt(0).toUpperCase() + value.slice(1)
 }
}
//使用
<span>{{msg | capitalize(arg1) }}

注意

  • 注册过滤器时,如果需要传递参数,必须从第二个参数开始,第一个参数为当前绑定的数据
  • 过滤器一般用于简单的文本格式化,如果是对多个状态数据,或是复杂的数据处理应该使用计算属性

注册指令

//全局注册
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
 // 当绑定元素插入到 DOM 中。
 inserted: function (el) {
 // 聚焦元素
 el.focus()
 }
})
//局部注册
directives: {
 focus: {
 // 指令的定义---
 }
}
//使用
<input v-focus />

二、Vue实例

Vue 实例,实则也就是 ViewModel(数据 + 函数),都是通过构造函数 Vue 创建

Vue 2.x教程之基础API

var vm = new Vue({
 name:'root',
 // 数据
 data: { a: 1 } / Function, // data类型根实例为Object,组件中为Function
 props:[]/{}, // 设置父组件传递给子组件的数据限制
 computed:{}, // 计算属性
 watch:{}, // 监控属性
 methods:{}, // 事件操作
 // 资源
 directives:{}, // 内部指令
 filters:{}, // 内部过滤器
 components:{}, // 内部组件
 // 生命周期:实例创建 => 编译挂载 => 组件更新 => 销毁
 beforeCreate(){
 console.log('beforeCreate ==> 实例创建')
 },
 created(){
 // 可以操作data, 但未生成DOM(未挂载)发起异步请求,初始化组件状态数据 data
 console.log('created ==> 实例创建完成,属性已绑定')
 },
 beforeMount(){
 console.log('beforeMount ==> 模板编译/挂载之前')
 },
 mounted(){
 // 已生成DOM到document中,可访问this.$el属性
 console.log('mounted ==> 模板编译/挂载之后')
 },
 beforeUpdate(){
 console.log('beforeUpdate ==> 组件更新之前')
 },
 updated(){
 // 操作DOM $('#box1')
 console.log('updated ==> 组件更新之后')
 },
 activated(){
 // 操作DOM $('#box1')
 console.log('activated ==> 组件被激活时(for keep-alive组件)')
 },
 deactivated(){
 console.log('deactivated ==> 组件被移除时(for keep-alive组件)')
 },
 beforeDestroy(){
 // 解除事件绑定,销毁非Vue组件实例等 如:this.$off('event1') select2.destory()
 console.log('beforeDestroy ==> 组件销毁之前')
 },
 destroyed(){
 console.log('destroyed ==> 组件销毁之后')
 }
})

三、计算属性与监听器

computed

任何复杂逻辑,都应当使用计算属性

可以像绑定普通属性一样在模板中绑定计算属性

声明式地创建依赖关系,计算属性的 getter 是干净无副作用的,因此也是易于测试和理解的。

<div id="example">
 <p>Original message: "{{ message }}"</p>
 <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
 el: '#example',
 data: {
 message: 'Hello'
 },
 computed: {
 // a computed getter
 reversedMessage: function () {
 // `this` points to the vm instance
 return this.message.split('').reverse().join('')
 }
 }
})

使用 methods 和 filter 也能达到计算属性同样的效果,但计算属性使模板更加简单清晰(模板中放入太多的逻辑会让模板过重且难以维护)。

计算属性有 计算缓存 的特性,计算属性是基于它的依赖缓存,只有在它的相关依赖发生改变时才会重新取值,而 methods 每次执行都会重新取值。

什么需要缓存?

假设我们有一个重要的计算属性 A ,这个计算属性需要一个巨大的数组遍历和做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter !如果你不希望有缓存,请用 method 替代。

getter与setter

计算属性默认为 getter

data: {
 firstName: 'Foo',
 lastName: 'Bar'
},
computed: {
 fullName: function () {
 return this.firstName + ' ' + this.lastName
 }
}

也可以添加 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

使用 watch 来监听data,实时响应数据的变化

例:监听用户输入,显示 正在输入...,输入完成时,显示 请稍等...,并发送异步请求,请求成功里,显示答案

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) {
 this.answer = '正在输入...'
 this.getAnswer()
 }
 },
 methods: {
 // _.debounce 是一个通过 lodash 限制操作频率的函数。
 // 在这个例子中,我们希望限制访问yesno.wtf/api的频率
 // ajax请求直到用户输入完毕才会发出
 getAnswer: _.debounce(
 function () {
 if (this.question.indexOf('?') === -1) {
  this.answer = '需要一个问题标识\'?\''
  return
 }
 this.answer = '请稍候...'
 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
  })
 },
 // 这是我们为用户停止输入等待的毫秒数
 500
 )
 }
})

使用 watch 选项允许我们执行异步操作(访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这是计算属性无法做到的。

四、样式绑定

使用 v-bind:class v-bind:style 来绑定样式

data:()=>{
 return {
 isActive: true,
 hasError: false,
 classObj:{
 'active':true,
 'align-left':true,
 },
 activeClass: 'active',
 errorClass: 'text-danger',
 styleObj:{
 color: 'red',
 fontSize: '13px'
 },
 activeColor: 'red',
 fontSize: 30,
 baseStyles:{color: 'red'},
 overridingStyles: { fontSize: '20px'}
 }
}

对象语法绑定

class 绑定的是对象的 key,如果对象的值为 true,则绑定 key

style 绑定的整个 对象

绑定 class

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

绑定style

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

数组语法绑定

class 绑定的是数组的 值

style 绑定的是数组中的 对象

<div v-bind:class="[activeClass, errorClass]">
// <div class="active text-danger">
// 使用三元表达式
<div v-bind:class="[isActive ? activeClass : '', errorClass]">
// 数组语法中使用对象语法
<div v-bind:class="[{ active: isActive }, errorClass]">
//绑定style
<div v-bind:style="[baseStyles, overridingStyles]">

五、条件渲染

v-if

切换元素的隐藏和显示 v-if、v-else、v-if-else

切换单个元素

<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>

切换多个元素

<template v-if="ok">
 <h1>Title</h1>
 <p>Paragraph 1</p>
 <p>Paragraph 2</p>
</template>

多条件判断

<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>

条件渲染默认会复用相同的组件,如果不复用元素,可添加 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>

v-show

用于切换元素样式属性 display 的 block 和 none

与 v-if 不同的是,元素隐藏时,并没有从DOM中删除,而 v-if 是删除了元素保存在缓存中。

注意 v-show 不支持 <template> 语法

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

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。

区分 v-if 与 v-show 的使用场景:

  • v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗
  • 如果需要频繁切换使用 v-show 较好
  • 如果在运行时条件不大可能改变则使用 v-if 较好

六、列表渲染

v-for='item of items / item in items' 用于迭代对象或数组中的元素

data: {
 items: [
 {message: 'Foo' },
 {message: 'Bar' }
 ]
 object: {
  firstName: 'John',
  lastName: 'Doe',
  age: 30
 }
}

基本用法

<ul id="example-1">
 <li v-for="item in items">
 {{ item.message }}
 </li>
</ul>

添加第二个参数可以获取当前迭代的 key 值

数组迭代

<ul id="example-2">
 <li v-for="(item, index) in items">
 {{ parentMessage }} - {{ index }} - {{ item.message }}
 </li>
</ul>

对象迭代

<div v-for="(value, key) in object">
 {{ key }} : {{ value }}
</div>

循环组件,向组件中传递数据

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

组件有自己的作用域,向组件中传递数据需要使用属性传递

v-for 具有比 v-if 更高的优先级

判断每一个todo项是否可显示

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

判断是否需要迭代todos

<ul v-if="shouldRenderTodos">
 <li v-for="todo in todos">
 {{ todo }}
 </li>
</ul>

添加 key 属性

提升重复渲染效率

<div v-for="item in items" :key="item.id">
 <!-- 内容 -->
</div>

数组监测

Vue重写了数组的变异方法,用于监测数组的更新

push()pop()shift()unshift()
splice()sort()reverse()

这些操作会改变原有数组,为变异方法

非变异方法返回新的数组,可以用于替换旧的数组

直接修改数组长度、利用索引修改数组的值,不会被监听到

过滤/排序

使用计算属性对原有数组进行过滤和排序

data: {
 numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
 evenNumbers: function () {
 return this.numbers.filter(function (number) {
  return number % 2 === 0
 })
 }
}

七、事件监听

v-on

v-on 用于监听绑定的事件

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

原生事件对象

使用 $event 传递原生事件对象

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

事件修饰符

methods 应该只处理纯粹的数据逻辑,而不是去处理 DOM 事件细节

     .stop 阻止事件冒泡

     .prevent 阻止默认事件

     .capture 使用捕获模式

     .self 只有当事件作用于本身时才触发

     .once 只绑定一次

<!-- 阻止单击事件冒泡 -->
<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>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 2.1.4-->
<a v-on:click.once="doThis"></a>
<!-- 组件中的原生事件 -->
<my-component @click.native="onClick"></my-component>

按键修饰符

监听键盘按下的键值

监听keyCode

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">

常用按键别名

  • .enter
  • .tab
  • .delete (捕获 “删除” 和 “退格” 键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
  • 2.1.0
  • .ctrl
  • .alt
  • .shift
  • .meta
<!-- 同上 -->
<input v-on:keyup.enter="submit">

按键组合

<!-- Alt + C -->
<input @keyup.alt.67="clear">
  • 所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上
  • 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。

八、表单输入绑定

使用 v-modal 给表单控件绑定相关数据(双向绑定)

v-modal 是一个语法糖

<input v-model="something">
// 等同于
<input v-bind:value="something" v-on:input="something = $event.target.value">

基本输入

// 文本框
<input v-model="message" placeholder="edit me">
// 文本域(支持换行)
<textarea v-model="message" placeholder="add multiple lines"></textarea>
// 复选框
// 单选(返回 true/false )
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
// 多选 (返回一个数组 ['jack', 'john'])
<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>
//单选框 (返回选中的值)
<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>
// 下拉框
// 单选 (返回选中的值)
<select v-model="selected">
 <option>A</option>
 <option>B</option>
 <option>C</option>
</select>
// 多选(返回一个数组 ['A','B'])
<select v-model="selected" multiple>
 <option>A</option>
 <option>B</option>
 <option>C</option>
</select>

当有选项有 value 属性时,选中时,返回 value, 当属性没有 value 时,选中时返回字符串或 true/false

<select v-model="selected">
 <option v-for="option in options" v-bind:value="option.value">
 {{ option.text }}
 </option>
</select>

绑定动态的value

v-model 绑定的 value 通常是静态字符串,对于 radio、checkbox、select,可以动态的使用v-bind设置value

<input
 type="checkbox"
 v-model="toggle"
 v-bind:true-value="a"
 v-bind:false-value="b"
>
// 当选中时
vm.toggle === vm.a
// 当没有选中时
vm.toggle === vm.b

修饰符

v-modal 的修饰符 .lazy、 .number、.trim

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
// 自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值)
<input v-model.number="age" type="number">
// 过滤用户输入的首尾空格
<input v-model.trim="msg">

自定义输入组件

使用 v-modal 自定义输入组件

前提条件,组件必须有 value 属性, 在有新的value时,可通过 input 事件获取更新的值。

自定义的货币输入组件

<currency-input v-model="price"></currency-input>
Vue.component('currency-input', {
 template: '
 <span>
  $
  <input
  ref="input"
  v-bind:value="value"
  v-on:input="updateValue($event.target.value)"
  >
 </span>
 ',
 props: ['value'],
 methods: {
 // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制
 updateValue: function (value) {
  var formattedValue = value
  // 删除两侧的空格符
  .trim()
  // 保留 2 小数位
  .slice(0, value.indexOf('.') + 3)
  // 如果值不统一,手动覆盖以保持一致
  if (formattedValue !== value) {
  this.$refs.input.value = formattedValue
  }
  // 通过 input 事件发出数值
  this.$emit('input', Number(formattedValue))
 }
 }
})

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
firefox 和 ie 事件处理的细节,研究,再研究 书写同时兼容ie和ff的事件处理代码
Apr 12 Javascript
flash 得到自身url参数的代码
Nov 15 Javascript
JS Jquery 遍历,筛选页面元素 自动完成(实现代码)
Jul 08 Javascript
js 弹出新页面避免被浏览器、ad拦截的一种新方法
Apr 30 Javascript
jQuery中[attribute*=value]选择器用法实例
Dec 31 Javascript
JavaScript实现Java中StringBuffer的方法
Feb 09 Javascript
浅析2种JavaScript继承方式
Dec 04 Javascript
详解js的事件代理(委托)
Dec 22 Javascript
JavaScript实现的搜索及高亮显示功能示例
Aug 14 Javascript
Vue.js实现表格渲染的方法
Sep 07 Javascript
详解Axios统一错误处理与后置
Sep 26 Javascript
Vue父子之间值传递的实例教程
Jul 02 Javascript
jQuery实现获取h1-h6标题元素值的方法
Mar 06 #Javascript
一道面试题引发的对javascript类型转换的思考
Mar 06 #Javascript
JavaScript函数参数的传递方式详解
Mar 06 #Javascript
jQuery实现遍历复选框的方法示例
Mar 06 #Javascript
jQuery.cookie.js使用方法及相关参数解释
Mar 06 #Javascript
jQuery Validate 相关参数及常用的自定义验证规则
Mar 06 #Javascript
jQuery简单实现遍历单选框的方法
Mar 06 #Javascript
You might like
PHP实现单例模式最安全的做法
2014/06/13 PHP
thinkphp判断访客为手机端或PC端的方法
2014/11/24 PHP
PHP读取大文件末尾N行的高效方法推荐
2016/06/03 PHP
PHP实现的AES双向加密解密功能示例【128位】
2018/09/03 PHP
Laravel配置全局公共函数的方法步骤
2019/05/09 PHP
在浏览器窗口上添加遮罩层的方法
2012/11/12 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
jQuery中height()方法用法实例
2014/12/24 Javascript
javascript中for/in循环及使用技巧
2015/09/01 Javascript
JavaScript知识点总结(十)之this关键字
2016/05/31 Javascript
详解node中创建服务进程
2017/05/09 Javascript
JavaScript变量作用域_动力节点Java学院整理
2017/06/27 Javascript
js实现前端图片上传即时预览功能
2017/08/02 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
vue-resource拦截器设置头信息的实例
2017/10/27 Javascript
angular 服务的单例模式(依赖注入模式下)详解
2018/10/22 Javascript
原生JS实现萤火虫效果
2020/03/07 Javascript
vue-router 按需加载 component: () =&gt; import() 报错的解决
2020/09/22 Javascript
Python 基础教程之闭包的使用方法
2017/09/29 Python
MAC中PyCharm设置python3解释器
2017/12/15 Python
用TensorFlow实现戴明回归算法的示例
2018/05/02 Python
浅析Python pandas模块输出每行中间省略号问题
2018/07/03 Python
对python产生随机的二维数组实例详解
2018/12/13 Python
Windows10下 python3.7 安装 facenet的教程
2019/09/10 Python
使用Rasterio读取栅格数据的实例讲解
2019/11/26 Python
python pandas.DataFrame.loc函数使用详解
2020/03/26 Python
Django数据结果集序列化并展示实现过程
2020/04/22 Python
python中return如何写
2020/06/18 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
服装厂厂长岗位职责
2013/12/27 职场文书
领导干部培训感言
2014/01/23 职场文书
我的中国梦演讲稿800字
2014/08/19 职场文书
追讨欠款律师函
2015/05/27 职场文书
大学入学感言
2015/08/01 职场文书
关于对TypeScript泛型参数的默认值理解
2022/07/15 Javascript