目录
vue简介
官网指路Vue.js
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。------摘自官网
- vue特点
1、采用组件化模块,提高代码复用率,且让代码更好维护;(一个.vue文件就是一个组件)
2、声明式编程,改变以往命令式编程方法,让开发人员无需直接操作DOM,提高开发效率;
3、使用虚拟DOM和优秀的Diff算法,尽量复用DOM节点;
- vue初识
vue安装
新手刚开始学习vue时,先不用安装脚手架,可以安装简易版vue,在script中引入即可,下载官网中的安装 — Vue.js开发版本,如下图:
正如截图所述,在开发阶段最好不要使用生产版本,否则调试时报的错都是底层错误,判断不出来哪里出错;
然后在js中引入该js脚本
<script src="js/vue.js"></script>
创建一个html文件
<body>
<div id="root">
<h1>Hello,{{name}}</h1>
</div>
<script>
const x = new Vue({
el: '#root', // el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串
data: { // data用于存储数据,数据供el所指定的容器去使用,一般data是一个对象
name: 'world!'
}
})
</script>
</body>
详解上述代码:
html中的{{ }}双层花括号为插值符,里面的参数为vue实例中的data里的属性;
const x = new Vue( { } )即为创建的vue实例,实例中有很多配置项,第一个一般为el,是用于将html中的容器与vue实例建立联系的配置,如此处将id=“root”的标签和vue实例联系到了一起(此处一般使用id来表示,当然也可以用类.表示),要用字符串表示;第二个配置项为data,用于存储数据,数据供el所指定的容器去使用。
注意:
一个vue实例不能接管多个vue容器,一个容器也不能接管多个vue实例,所以容器和实例之间是一对一关系;
若实例中的数据data太多了,则就不能把属性值全放在data里面,此时就有了组件的概念;
el和data的另外一种写法
el:
之前使用的是在new Vue时候配置el属性方法;
方法二即先创建实例,随后再通过vm.$mount('#root')指定el的值,其中vm是创建的实例对象,mount即为挂载的意思,这种方法也可使容器与实例对象产生关联;
data:
之前介绍的data方法为对象式方法;
方法二即为函数式写法,将data包装为一个函数,记住,这种方式一定要加return
data() {
return {
name1: 'vue'
}
}
并且该种方式在后面用到组件时必须被使用,另外需要注意,由vue管理的函数最好使用普通函数,切记不要使用箭头函数,因为要确保this指向的始终是vue实例对象~
MVVM模型
vue虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。
M:模型(Model):对应data中的数据;
V:视图(View):对应模板,即html部分;
VM:视图模型(ViewModel):即Vue实例对象
data中所有的属性,最后都出现在了vm(实例对象)身上;
vm(实例对象)上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用;
-----这就叫做数据代理,即通过vm对象来代理data对象中属性的操作(读/写),使用数据代理可以更加方便的操作data中的数据;它的基本原理如下:
通过Object.defineProperty()把data对象中所有属性添加到vm上,为每一个添加到vm上的属性,都指定一个getter和setter,其中getter在获取参数的时候被触发,setter则是在修改参数的时候被触发;在getter或setter内部去操作(读/写)data中对应的属性。
模板语法
Vue.js使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有Vue.js的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解析;
在底层的实现上,Vue将模板编译成虚拟DOM渲染函数,结合响应系统,Vue能够智能的计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少;------摘自官网
插值
- 文本
数据绑定最常用的形式是使用双大括号的文本插值:{{ }}
括号中的值会被替代为对应实例对象中data数据对象上对应的属性值,且当绑定的属性值发生改变时,插值处的内容都会更新;
当然,使用v-once指令,也可以将其变为一次性插值,即当数据改变时,插值处的内容不会被更新;
- Attribute
上述插值方法无法作用在HTML属性中,此时就要用到v-bind指令;如:
<div v-bind:id="dynamicId"></div>
- 使用JavaScript表达式
Vue.js提供了完全的JavaScript表达式支持;如:
{{ number+1 }}
表达式会在所属Vue实例的数据作用域下作为JavaScript被解析。有个限制就是,每个绑定都只能包含单个表达式,而不能是语句!(表达式和语句不一样哦!)
指令
指令是带有v-前缀的特殊属性。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。------摘自官网
- 参数
一些指令能够接收一个“参数”,在指令名称之后以冒号表示,例如:v-bind指令可用于响应式的更新HTML属性
<a v-bind:href="url">...</a>
v-bind绑定的参数,告诉v-bind指令将该元素的href属性与表达式url的值绑定;v-bind用于单向数据绑定,即用于将vue实例中的data体现到页面中;
v-model用于双向绑定,即数据不仅能从data流向页面,还可以从页面流向data;一般用于表单类元素上,如input/select/textarea等;v-model会忽略所有表单元素的value/checked/selected等属性的初始值,会将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的data选项中声明初始值。
<input type="text" v-model:value="name"> //将input中的默认值与data中的name属性双向绑定
v-bind可缩写为:绑定的参数=“表达式”,如上述就可简写为:
<a :href="url">...</a>
v-model可缩写为v-model="绑定的参数",可简写为:
<input type="text" v-model="name">
v-model在内部为不同的输入元素使用不同的属性 并抛出不同的事件:
- text 和 textarea 元素使用value属性和input事件;
- checkbox 和 radio 使用checked属性和change事件;
- select 字段将value作为属性并将change作为事件。
事件处理
监听事件
可用v-on指令监听DOM事件,并在触发时运行一些JavaScript代码;
vue实例对象中的配置项methods指方法集合(即事件的回调函数)
<div id="root">
<button v-on:click=mes()>点我!</button>
</div>
<script>
// Vue.config.productionTip = false // 阻止vue在启动时生成生产提示
const x = new Vue({
el: '#root', // el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串
data: { // data用于存储数据,数据供el所指定的容器去使用,一般data是一个对象
name: 'world!'
},
methods: {
mes() {
alert('被骗了吧!')
}
}
})
</script>
也可写成下述方法:
<div id="root">
<button v-on:click="mes()">点我!</button>
</div>
<script>
// Vue.config.productionTip = false // 阻止vue在启动时生成生产提示
const x = new Vue({
el: '#root', // el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串
data: { // data用于存储数据,数据供el所指定的容器去使用,一般data是一个对象
name: 'world!'
},
methods: {
msg: function() {
alert('被骗了吧!')
}
}
})
</script>
在模板中写方法的时候,msg若不传参数,则括号可加可不加,methods配置项中的方法都有一个默认参数event,若想传其它参数,则正常传即可,若想保留原始参数event,则要在括号内用$event占个位置;
<div id="root">
<button v-on:click="mes(6, $event)">点我!</button>
</div>
<script>
// Vue.config.productionTip = false // 阻止vue在启动时生成生产提示
const x = new Vue({
el: '#root', // el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串
data: { // data用于存储数据,数据供el所指定的容器去使用,一般data是一个对象
name: 'world!'
},
methods: {
mes(number, event) {
// alert('被骗了吧!')
console.log(event, number)
}
}
})
</script>
也可写成下述:
<div id="root">
<button v-on:click="mes(6, $event)">点我!</button>
</div>
<script>
// Vue.config.productionTip = false // 阻止vue在启动时生成生产提示
const x = new Vue({
el: '#root', // el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串
data: { // data用于存储数据,数据供el所指定的容器去使用,一般data是一个对象
name: 'world!'
},
methods: {
mes: function(number, event) {
// alert('被骗了吧!')
console.log(event, number)
}
}
})
</script>
v-on: xxx可简写为@xxx事件,如v-on:click可简写为@click;
事件修饰符
主要有如下几种:
.prevent: 表示组织默认事件(常用);
.stop:表示阻止事件冒泡(常用);
.once:表示事件只触发一次(常用);
.capture:表示使用事件的捕获模式,与冒泡模式相反的模式,见前面讲述;
.self:表示只有event.target是当前操作的元素时才触发事件;
.passive:表示事件的默认行为立即执行,无需等待事件函数回调执行完毕;
示例如下:
<div id="root">
<button @click.once="mes(6, $event)">点我!</button>
</div>
事件修饰符可以连用,如:
<div id="root" @click="mes(6, $event)">
<button @click.once.stop="mes(6, $event)">点我!</button>
</div>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用@click.prevent.self会阻止所有的点击,而@click.self.prevent只会阻止对元素自身的点击。
按键修饰符
在监听键盘事件时,经常需要检查详细的按键。Vue允许为v-on在监听键盘事件时添加按键修饰符,常用的按键别名如下:
回车(enter)、删除(delete)、退出(esc)、空格(space)、换行(tab)、上(up)、下(down)、左(left)、右(right)等
<input v-on:keyup.enter="submit"> // 在键入回车抬起的时候触发事件
注意:在使用keyup时,ctrl/alt/shift/win键,要在按下修饰符的同事,再按下其它键,释放其它键的时候,才会触发事件;
除以上常用的按键,也可以使用按键原始的key值去绑定,但要注意将其转换为kebab-case(用短横线命名)
<input v-on:keyup.page-down="onPageDown">
上述代码则在按键为PageDown弹起的时候被调用;
当然也可以连用按键修饰符:
<input v-on:keyup.ctrl.y="onPageDown">
只有在同时键入ctrl和y时才触发事件;
计算属性与侦听器
计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的,在模板中放入太多的逻辑会让模板过重且难以维护。所以一般用data配置项放置属性,在computed配置项中放置计算属性;对于任何复杂逻辑,应当使用计算属性;
<div id="root">
姓名: <input type="text" v-model="fullname"> </br>
班级: <input type="text" v-model="classname"> </br>
姓名班级: <span>{{nameAndClass}}</span>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
fullname: '小明',
classname: '一年级',
},
computed: {
nameAndClass: {
get: function() {
return this.fullname + '是' + this.classname + '的学生'
}
}
}
})
</script>
get函数什么时候被调用?
get函数会被调用,并且其返回值就是nameAndClass的值;get函数在初次读取nameAndClass计算属性和所依赖的数据发生变化时会被调用(所依赖的数据即计算该属性需要用到的data中的属性值);
当要修改计算属性时,应该调用什么函数?
若计算属性要被修改,则此时需要set函数去相应修改,且set函数会导致计算时依赖的数据发生变化;
<div id="root">
姓名: <input type="text" v-model="fullname"> </br>
班级: <input type="text" v-model="classname"> </br>
姓名班级: <span>{{nameAndClass}}</span>
</div>
<script>
const vm = new Vue({ // 此处要传进来需要修改的参数
el: '#root',
data: {
fullname: '小明',
classname: '一年级',
},
computed: {
nameAndClass: {
get: function() {
return this.fullname + '-' + this.classname
},
set: function(value) {
console.log(value);
const arr = value.split('-');
console.log(arr);
this.fullname = arr[0];
this.classname = arr[1];
}
}
}
})
</script>
当确定该计算属性不需要修改的时候,可只是用get函数,此时可以简写为如下:
<div id="root">
姓名: <input type="text" v-model="fullname"> </br>
班级: <input type="text" v-model="classname"> </br>
姓名班级: <span>{{nameAndClass}}</span>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
fullname: '小明',
classname: '一年级',
},
computed: {
nameAndClass() {
return this.fullname + '-' + this.classname
}
}
})
</script>
记住:计算属性是一个属性,所以在使用的时候,用的是nameAndClass,而不是nameAndClass();
- 计算属性与方法methods相比有啥异同?
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应性依赖发生改变时它们才会重新求值,而在每当触发重新渲染时,调用方法将总会再次执行函数;在不希望有缓存的情况下,使用方法methods;
侦听器
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么Vue通过watch配置项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<div id="root">
<h2>今天心情很{{mood}}</h2>
<button>点我换种心情</button>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
isHappy: true
},
computed: {
mood() {
return this.isHappy ? '好' : '坏'
}
},
watch: {
isHappy: {
handler(newValue, oldvalue) {
console.log('心情被改变了', newValue, oldvalue);
}
}
}
})
</script>
watch监视的一定是个属性值!当被监视的属性值发生变化时,watch中的handler函数就会被调用,同时传入两个参数,一个是改变后的值,另一个是改变之前的值;并且被监视的属性值也是一个配置对象;
watch监视的第二种写法是在定义完Vue实例后,使用$vm.watch方法:
<div id="root">
<h2>今天心情很{{mood}}</h2>
<button>点我换种心情</button>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
isHappy: true
},
computed: {
mood() {
return this.isHappy ? '好' : '坏'
}
}
})
vm.$watch('isHappy', {
handler(newValue, oldvalue) {
console.log('心情被改变了', newValue, oldvalue);
}
})
</script>
- 若要监视多级结构下的属性应该如何使用?
声明deep:true即可
- 若要初始时调用一次handler?
加入immediate: true即可
- 若不需要初始化和多级深监视,是否有简便方法?
<div id="root">
<h2>今天心情很{{mood}}</h2>
<button>点我换种心情</button>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
isHappy: true
},
computed: {
mood() {
return this.isHappy ? '好' : '坏'
}
},
watch: {
isHappy(newValue, oldvalue) {
console.log('心情被改变了', newValue, oldvalue);
}
}
})
</script>
此时函数名,就是要监视的属性值,函数参数即为handler中的参数,其余不变;
- watch和computed有何异同?
计算属性不能开启异步任务,因为它直接依赖于返回值,而监视属性则可以,因为它不靠返回值,所以当watch和computed都能实现任务时,使用computed,但是当有异步任务时,则就要使用watch方法;
注意:
- 所有能被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象;
- 所有不被Vue管理的函数,如定时器的回调函数、Ajax的回调函数、Promise的回调函数等,最好都写成箭头函数,这样才能保证this的指向是vm或组件实例对象;