vue学习笔记(更新中)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
简介
此文章用于记录vue学习过程中笔记知识点。
使用Vue写一个"helloworld"
前置准备
使用vue前需要到vue官网下载vue的库vue.js并且将文件vue.js正确引入到html结构中。
点击连接点击如下图的"开发版本"进行vue.js的下载。
开发版本占内存比较大但是有vue的报错提示信息比较适合学习和调试使用。
生产版本(压缩版)占内存较小没有错误信息的提示信息比较适合上线发布的程序使用。
将下载的vue.js引入html文件
// 根据自己实际情况引入正确路径
<script src="../vue.js"></script>
代码书写
先看代码
// 1.引入vue.js文件
<script src="../vue.js"></script>
<body>
// 2.准备一个模板容器
<div id="root">
<h1>{{info}}</h1>
</div>
<script>
// 3.编写vue实例格式
new Vue({
// 4. 绑定模板容器在此可使用CSS选择器
el:"#root",
// 5. 编写数据模型
data:{
info:"Hello,World"
}
})
</script>
</body>
界面展示
说明 代码中在DOM结构准备一个容器是必要的并且需要将此容器绑定到vue实例中从上述代码可以看出vue实例的格式是固定的只是其中的属性多少有无不同。也许有些看不懂代码中的{{info}}等地方不要紧先记住vue实例的固定写法格式即可其他的下面会提及。
MVVM模型理解
为什么要了解MVVM模型
我们可以先看vue官网对MVVM的一些说明
可以看到虽然vue没有完全遵循MVVM但是此模型思想是重要的因此我想我们有必要去了解MVVM。MVVM可以看为M-V-VM。
1. M模型(Model) 对应 vue实例"data" 中的数据
2. V视图(View) 模板DOM结构
3. VM视图模型(ViewModel) Vue 实例对象
我们可以看如下代码
<div id="root">
<!-- M-V-VM中的V模板视图 -->
<h1>姓名:{{name}}</h1>
</div>
<script>
var vm = new Vue({ //M-V-VM中的VM vue实例
el:"#root",
data:{ //M-V-VM中的M 数据模型
name:"Maohe"
}
})
</script>
VMvue实例是V模板和M数据模型之间的桥梁。
插值语法和指令语法
插值语法
1. 功能: 用于解析标签体内容。
2. 语法: {{xxx}} xxxx 会作为 js 表达式解析。
用法
<body>
<div id="root">
// 插值语法
<h1>姓名:{{name}}</h1>
</div>
<script>
new Vue({
el:"#root",
data:{
name:"MaoHe"
}
})
</script>
</body>
页面效果
指令语法
1. 功能: 解析标签属性、解析标签体内容、绑定事件。
2. 举例v-bind:href = 'xxxx' xxxx 会作为 js 表达式被解析。
3.说明vue中的指令有很多在此使用v-bind和v-model演示用法。
指令v-bind
1. 语法v-bind:href ="xxx" 或简写为 :href
2. 特点数据只能从 data 流向页面数据单向绑定
3.使用范围任何标签都可用此指令
用法-作用
<div id="root">
// 使用v-bind可以跟vue实例data中对应模型绑定
<a v-bind:href="rul">点击跳转</a>
// 简写形式
<a :href="rul">点击跳转</a>
</div>
<script>
new Vue({
el:"#root",
data:{
rul:"http://www.baidu.com"
}
})
</script>
使用v-bind可以给标签中属性做绑定当vue中data数据模型发生变化的时候页面模板设置有指令v-bind的标签属性也会跟着改变。
重要特性为什么data中的数据发生变化模板里的数据会跟着改变
因为当data中数据发生改变的时候vue会重新加载模板所以解析到标签使中用了data中的数据时就会重新赋值就会达到当vue中data发生变化则模板中数据会跟着变化。
指令v-model
1. 语法v-mode:value="xxx" 或简写为 v-model="xxx"
2. 特点数据不仅能从 data 流向页面还能从页面流向 data数据模型。
3.适用范围只有表单元素可以使用因为v-model是服务与value属性的是双向绑定如果页面没有输入那么数据双向绑定也就没有了意义。
用法-作用
<div id="root">
// 使用指令v-model 数据双向绑定
姓名<input type="text" v-model:value="name">
// 简写形式value可以省略
姓名<input type="text" v-model="name">
</div>
<script>
new Vue({
el:"#root",
data:{
name:"MaoHe"
}
})
</script>
效果
当我们改变输入框中内容时vue实例中的data也会跟着改变相同的我们改变data中的数据页面的输入框内容也会改变。这就是数据的双向绑定。这就是区别于v-bind的重要特点。
v-model操作的是表单元素也就是说只要标签中有value属性的都可以使用指令v-model。例如单选框多选框等等。
vue中的el和data的两种写法
说明在vue实例el和data书写的时候还有另一种格式在vue实例外书写。看如下格式
el的另一种写法
<div id="root">
// 使用指令v-model 数据双向绑定
姓名<input type="text" v-model:value="name">
// 简写形式value可以省略
姓名<input type="text" v-model="name">
</div>
<script>
new Vue({
//el:"#root",
data:{
name:"MaoHe"
}
})
// 在vue实例后添加el容器的绑定
vm.$mount("#root")
</script>
data的另一种写法
<div id="root">
姓名<input type="text" v-model:value="name">
</div>
<script>
new Vue({
el:"#root",
// 对象式的写法
// data:{
// name:"MaoHe"
// }
// 函数式的写法
data:function(){
return{
name:"MaoHe"
}
}
})
</script>
数据代理
通过一个对象代理对另一个对象中属性的操作读/写 例如对象a代理对象b中的name属性当我们操作a中的name属性实际上改变的是b中的name属性。
方法defineProperty() 说明原生数据代理
在说vue的数据代理之前需要先说明方法defineProperty()因为vue的数据代理底层使用的就是此方法。所以有必要了解此方法。
Object.defineProperty()
方法会直接在一个对象上定义一个新属性或者修改一个对象的现有属性并返回此对象。参数
Object.defineProperty(obj, prop, descriptor)
obj要定义属性的对象。
prop要定义或修改的属性名称。
desctipt要定义或修改的属性描述符。
需求现有对象obj1和对象obj2我们让obj2代理obj1中的name属性。如下
<script>
obj1 = {name:"Maohe"};
obj2 = {age:18};
//当使用obj2操作name属性时实际变动的是obj1中的name属性。
Object.defineProperty(obj2,"name",{
get() {
return obj1.name;
},
set(value){
obj1.name = value;
}
})
//测试
console.log(obj2.name); //输出Maohe
console.log(obj1.name); //输出Maohe
obj2.name = "Tom";
console.log(obj2.name); //输出Tom
console.log(obj1.name); //输出Tom
</script>
通过上述代码容易看出对象obj2中本来是没有name属性的但是通过defineProperty()方法设置了数据代理使得obj2可以操作obj1中的name属性。就是将obj1中的name属性代理给了obj2
vue中的数据代理
当我们访问模型data中的数据时例如一个属性name我们在插值表达式中是直接写name而不是data.name在此就是做了数据代理而且data的数据存在VUE实例中也不叫data而是_data。
<div id="root">
<h1>{{name}}</h1>
</div>
<script>
var vm = new Vue({
el:"#root",
data:{
name:"MaoHe"
}
})
</script>
我们可以看一下vue实例中的东西(在控制台输出vm)
一个数据代理图示
总结
当我们在data中声明了属性这些属性就会被vue自动的加上数据代理将代理对象放到vm中例如如上图例在data中声明了name和address属性vue会先将两个属性添加到vm的_data中然后使用defineProperty(方法给两个属性设置代理将name和address代理者放到vm中。当操作vm中的name和address实际上改变的是_data中的name和address。
事件处理绑定监听
事件处理也就是给某节点绑定事件。
如下是书写的概述
1. v-on:xxx="fun" ---正常写法xxx是事件名称如点击click
2. @xxx="fun" ---@简写
3. @xxx="fun(参数)" ---有框号用于传递参数
4. 默认事件形参: event ---接收事件参数没有参数时
5. 隐含属性对象: $event ---接收事件参数有参数时
指令 v-on用于事件监听
用法
// 需求当点击按钮触发showAlert方法出现弹窗。
<div id="root">
<h1>指令v-on的说明</h1><br>
// 一般书写
<button v-on:click = "showAlert">点击弹窗</button>
// 简写形式
<button @click = "showAlert">点击弹窗</button>
</div>
<script>
new Vue({
el:"#root",
data:{},
methods: {
showAlert() {
alert("我是弹窗...")
}
},
})
</script>
方法参数说明
在上如案例中代码v-on:click = "showAlert" 调用的时候可以不用括号代表不传参数的调用方法但是在vue的方法调用中会有一个默认的事件对象不用传入也可以接收到。看如下
new Vue({
el:"#root",
data:{},
methods: {
showAlert(e) {
console.log(e);
alert("我是弹窗...")
}
},
})
当我们触发点击事件后会打印e这个e就是事件对象。输入如下
会有触发事件时的一些状态信息。例如触发事件的节点点击页面的位置信息等等。
其实如上方式输入事件对象是一种特殊也就是当没有参数的方法调用时上面的方式是有效的但是如果有参数的调用那么将不会接收到事件对象了。如下
<div id="root">
<h1>指令v-on的说明</h1><br>
<!-- <button v-on:click = "showAlert">点击弹窗</button> -->
<button @click = "showAlert(18)">点击弹窗</button>
</div>
<script>
new Vue({
el:"#root",
data:{},
methods: {
showAlert(args1,args2,agrs3) {
//打印事件对象
console.log(args1); //18
console.log(args2); //undefined
console.log(args3); //报错args3 is not defined
alert("我是弹窗...")
}
},
})
</script>
那么我们该如何获取事件对象呢可以看如下代码
<div id="root">
<h1>指令v-on的说明</h1><br>
<!-- <button v-on:click = "showAlert">点击弹窗</button> -->
<button @click = "showAlert($event,18)">点击弹窗</button>
</div>
<script>
new Vue({
el:"#root",
data:{},
methods: {
showAlert(args1,args2,agrs3) {
//打印事件对象
console.log(args1); //事件对象
console.log(args2); //18
console.log(args3); //报错args3 is not defined
alert("我是弹窗...")
}
},
})
</script>
事件修饰符阻止默认事件阻止冒泡...
先介绍vue中的事件修饰符接下来再演示用法。
Vue中的事件修饰符
1、prevent 阻止默认事件。
2、stop阻止事件冒泡。
3、once事件只触发一次。
4、capture使用事件的捕获模式。
5、self只有event.target是当前操作的元素是才触发事件。
6、passive事件的默认行为立即执行无需等待事件回调执行完毕。
事件修饰符的用法
事件修饰符的使用方式是简单的下面我们就使用preven阻止默认事件和stop阻止事件冒泡做演示即可。其他的用法都一样只是功能不同罢了。
阻止默认事件演示
<div id="root">
// 阻止默认事件
// 当点击时a标签的默认事件是跳转到href属性的地址
// 我们使用链式编程的方式书写.prevent后将不再会跳转
<a @click.prevent= "showAlert" href="http://www.baidu.com">点击跳转</a>
</div>
<script>
new Vue({
el:"#root",
data:{},
methods: {
showAlert() {
alert("我是弹窗!")
}
},
})
</script>
阻止事件冒泡演示
<div id="root">
<div title="我是父标签" id="father" @click="bubble">
父标签
<!-- // 阻止事件冒泡 -->
<div title="我是子标签" id="sun" @click="bubble">
子标签
</div>
</div>
</div>
<script>
new Vue({
el:"#root",
data:{},
methods: {
showAlert() {
alert("我是弹窗!")
},
bubble(){
alert("我是div点击触发的弹窗...")
}
},
})
</script>
页面效果
说明根据事件冒泡原理当我们点击子标签后红色背景盒子会触发点击事件然后会自动冒泡到父标签父标签又会触发一次同一个点击事件。也就是会出现两次弹窗bubble方法会执行两次。
那么在vue中阻止事件冒泡方式很简单看如下代码在上面代码的基础上进行改动
<!-- 只需要在子标签@click后添加.stop即可阻止事件冒泡 -->
<div title="我是父标签" id="father" @click="bubble">
父标签
<!-- // 阻止事件冒泡 -->
<div title="我是子标签" id="sun" @click.stop="bubble">
子标签
</div>
</div>
键盘事件
在vue中绑定键盘事件的方式和上面的点击事件是一样的@keydown,@keyup...这些不值得多说值得提的是我们想要确定用户点击了某个按键和组合键的判断这是我们需要注意的地方。
需求 想要判断用户是否按下了x键。
<div id="root">
<input type="text" @keydown.x="keyDownX" >
</div>
<script>
new Vue({
el:"#root",
methods: {
keyDownX() {
alert("按下了x键")
}
},
})
</script>
需求判断用户是否按下了esc键
<div id="root">
<input type="text" @keydown.esc="keyDownESC" >
</div>
<script>
new Vue({
el:"#root",
methods: {
keyDownESC() {
alert("按下了esc键")
}
},
})
</script>
说明为什么我们可通过@keydown.x @keydown.esc就可以锁定x或esc键呢
其实是vue给我们这些键设置了别名。一些字母和一些功能键可以这样绑定但是如果需要我们判断用户是否按下数字键123等等那么我们不就没招了吗当然不是下面讲解但是需要先了解vue帮我们封装了哪些内置的按键别名。
==========vue内置的键盘按键别名==============
回车 => enter
删除 => delete此处捕获"删除"和"退格"
退出 => esc
空格 => space
制表符 => tab
上 => up
下 => down
左 => left
右 => right
=======================================
keyCode的方式绑定按键通用方法
一个演示
需求判断用户是否按下数字键1
<div id="root">
<input type="text" @keydown.97="keyDown" >
</div>
<script>
new Vue({
el:"#root",
methods: {
keyDown() {
// console.log(e.keyde);
alert("按下了数字键1")
}
},
})
</script>
看到@keydown.97也许会有疑问这个97为什么可以代表数字1这其实是数字1的键码也就是ascii码表中数字1的码值不晓得的可以百度一下ascii码表就会看到一张表ascii码表上有着所有字符代表的数字。
但是如果每次我们想要知道某个按键的键码那么每次都去看ascii码表就会太麻烦了因此我们可以动态的某个键的键码可以看如下代码
<div id="root">
<input type="text" @keydown="keyDown" >
</div>
<script>
new Vue({
el:"#root",
methods: {
keyDown(e) {
// 通过事件对象获取用户输入的键的键码
console.log(e.keyCode);
}
},
})
</script>
这样用户就可以通过此方式获取任意键的键码通过@keydown.键码来绑定事件了。
需求判断用户是否按下了alt + a 组合键
<div id="root">
<input type="text" @keyup.alt.a="keyDown" >
</div>
<script>
new Vue({
el:"#root",
methods: {
keyDown() {
// console.log(e.keyCode);
alert("按下了alt + a 组合键")
}
},
})
</script>
如上就是组合键的判断类似想要什么键组合就链式编程连起来即可。
自定义键名
说明如果一个键经常使用的话那么使用键码来绑定的话可读性可能没那么好那么我们就想能不能像vue中的内置别名一样我们也设置常用的键的别名使用时直接通过@keyup.自定义键名就能绑定事件。
自定义键别名给delete设置键别名为del。
首先我们需要先知道delete的键码通过上面我们已经知道该如何获取一个键的键码要么通过事件对象获取keycode要么去查ascii码表delete的键码为46。
那么我们就可以这样设置自定义键别名
<div id="root">
// vue内置delete键别名绑定事件
<input type="text" @keyup.delete="keyDown" >
// 通过用户自定义键别名绑定事件
<input type="text" @keyup.del="keyDown" >
</div>
<script>
// 自定义键别名
Vue.config.keyCodes.del = 46; //delete键的键码为46
new Vue({
el:"#root",
methods: {
keyDown(e) {
alert("Delete...")
}
},
})
</script>
计算属性
概述
1. 什么是计算属性作用要显示的数据不存在要通过已有的属性计算得来。
2. 书写位置在 computed 对象中定义计算属性。
3. 数据展示在页面中使用{{方法名}}来显示计算的结果
作用演示
需求有两个输入框一个输入姓名的姓一个输入姓名的名当用户输入后将自动识别将全名显示出来。
界面
代码使用计算属性
<div id="root">
姓<input type="text" v-model="firstName"><br>
名<input type="text" v-model="lastName"><br><br>
全名<span>{{fullName}}</span>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
computed:{
fullName:{
get(){
return this.firstName + this.lastName
}
}
}
})
</script>
说明使用计算属性格式看代码演示在computed关键字中将计算属性名写上在计算属性作用域中写get和set方法我们不需要设置fullName所以不需要设置set方法在其中当模板解析到{{fullName}}时会调用到get方法但是不是每一次都会调用一次计算属性computed存在缓存在一定条件下才会调用此条件下面会说到在案例中将返回值给到fullName属性。
优势
其实在上面的案例中我们是可以直接用原生JS书写方法在方法中写拼接语句也可以实现但是对比计算属性在此计算属性优势还是比较大的因为计算属性存在缓存机制方法调用较少效率更高些。
缓存机制当我们调用get函数后其实底层是会给get函数的返回值做缓存的当计算属性的依赖数据没有改变也就是fullName的firstName和lastName没有改变的时候当再次访问fullName属性时不需要再次调用get方法获取返回值给fullNane属性而是从缓存中将数据给到fullName但是也许会有一个疑问当依赖数据发生改变的时候那么还从缓存中拿而不重新调用get方法获取返回值给计算属性的话计算属性数据不就过时了吗其实不然在了解get方法的调用时机后会解决改疑问调用时机如下会提到。
总结
1.看案例可以看出我们的计算属性是不需要事先在vm的data中定义的。
2.底层原理底层还是使用到了数据代理object.defineproperty()中提供的get和set方法。
这样使我们才可以在插值语法中直接使用计算属性。
3.get函数调用时机
(1).第一次解析模板读取到计算属性时执行将返回值给到计算属性。
(2).当计算属性使用的数据依赖发生改变时会调用在案例中就是当firstName和lastName发生变化时会重新调用get方法将新拼接的全名给到fullName。
简写形式
从上面的案例中看出计算属性的书写还是有点繁琐的其实当计算属性中只有get方法是可以简写的。书写形式如下
<div id="root">
姓<input type="text" v-model="firstName"><br>
名<input type="text" v-model="lastName"><br><br>
全名<span>{{fullName}}</span>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
computed:{
fullName:function(){
return this.firstName + this.lastName;
}
}
})
</script>
监听属性
概述
1. 书写形式通过 vm 对象的$watch()或 watch 配置来监视指定的属性。
2. 作用当监听的属性变化时, 回调函数自动调用, 在函数内部进行计算。
作用演示
演示需求监听data中的flag属性当flag变化时控制台打印提示。
页面
点击按钮控制台提示
代码
<div id="root">
<span>当前flag值为:{{flag}}</span><br><br>
<button @click="change">点击切换</button>
</div>
<script>
new Vue({
el:"#root",
data:{
flag:true
},
watch:{
flag:{
handler(newValue,oldValue){
console.log("flag变化了,原为:",oldValue,"变化为",newValue,);
}
}
},
methods: {
change() {
this.flag = !this.flag;
}
},
})
</script>
说明如上案例我们对flag属性进行了监视当flag值发生改变的时候我们会在控制台输出提示。这是一种最简单的属性监视。
监视多级属性-深度监视
案例需求现在一个属性people属性peole下又有name和age属性。此时我们想要监视people下的name属性当name属性变化时我们控制台输入提示。
页面
代码
<div id="root">
<span>name值为{{people.name}}</span><br><br>
name值<input type="text" v-model="people.name">
</div>
<script>
new Vue({
el:"#root",
data:{
people:{
name:"Maohe",
age:18
}
},
watch: {
'people.name':{
handler(){
console.log("people下面的name变化了...");
}
}
}
})
</script>
过渡说明看了上面的案例我们知道了如何监视多级属性下的某个属性是否变化但是如果我们想要监视多级属性的父属性也就是上面案例的people属性如果我们像监视people属性是否变化那么只有当people下面的所有属性name和age都变化时才会触发handler这是一种情况但是在一般情况下我们想要达到的效果是只要people下面的任一属性发生变化那么handler就会触发。这时我们就要使用深度监视。
开始深度监视
设置配置项deep为true即为开启深度监视。
简写形式
值得注意的是使用如上的简写形式会有一些限制就是不能够深度监视属性因为没有地方设置配置项deep为true了使用简写形式就只能默认使用普通监视。但基本也够用是否使用深度监视需要看开发时的数据结构。
class绑定
此处的classs绑定说的是使用vue对DOM标签绑定上类名的一些格式。
概述
1. 书写格式 :class='xxx'
2. 书写形式一表达式是字符串: 'classA'
3. 书写形式二表达式是对象: {classA:isA, classB: isB}
4. 书写形式三表达式是数组: ['classA', 'classB']
作用演示
需求当我们在div标签中使用class指定了类名后我们再想要去给此div盒子追加类名那么这时候我们有两种选择第一种是使用原始方式在类名后空格追加另一种是使用vue的:class形式追加。两种方式比较说明在下面会说到接下来看两种形式的代码书写。
原始方式给标签绑定多了类名
<div class="c1 c2">
<!--原始方式绑定多个class-->
</div>
vue中class绑定的方式
<div id="root">
<div class="c1" :class="divClassName">
// vue中绑定class
</div>
<script>
new Vue({
el:"#root",
data:{
divClassName:"c2"
}
})
</script>
</div>
说明上述的代码中使用了:class的方式进行class的绑定这样写有些人会觉得是多次一举因为书写好像比较繁琐要多写:class和多定义数据模型但是其实这样的可扩展性更好一些想要修改直接在模型中修改即可。
数组和对象形式绑定class
在上述的例子中我们只能多绑定一个class那么当我们要绑定更多class的时候使用上述的方式显然不行了这时候就需要使用到数组和对象的形式才可以将多个class绑定上。
数组形式绑定class
<div id="root">
<div class="c1" :class="classArray">
</div>
<script>
new Vue({
el:"#root",
data:{
classArray:["c2","c3"]
}
})
</script>
</div>
对象形式绑定class
<div id="root">
<div class="c1" :class="classObj">
</div>
<script>
new Vue({
el:"#root",
data:{
classObj:{
//使用true或false决定是否使用此class
c2:true,
c3:true
}
}
})
</script>
</div>
说明在对象绑定class中我们发现是比较特殊的在对象中类名是键而值是布尔值使用布尔值控制是否使用此属性还是比较实用的。
style绑定
vue中style绑定和class绑定的用法非常相似只有功能有所区别一个是绑定类名一个是绑定样式罢了。
作用演示
需求使用vue的style绑定给一个div盒子添加一个背景和宽高的样式。
<div id="root">
<div :style="styleObj">
vue进行style绑定
</div>
</div>
<script>
new Vue({
el:"#root",
data:{
styleObj:{
width:"200px",
height:"200px",
backgroundColor:"red"
}
}
})
</script>
值得注意的是使用上述对象的形式添加样式当样式属性名是由"-"连接的那么我们在对象域中就应该使用小驼峰的格式书写样式名。比如background-color变成backgroundColor。
绑定style的其他方式
其实在vue中绑定style不只上述的对象形式绑定还可以直接在标签上书写以及使用数组的形式书写。如何使用看如下代码
直接在标签上定义
<div :style="{backgroundColor:'red'}">
vue进行style绑定
</div>
绑定数组
<div id="root">
<div :style="[styleA,styleB]">
vue进行style绑定
</div>
</div>
<script>
new Vue({
el:"#root",
data:{
styleA:{
width:"200px",
height:"200px"
},
styleB:{
backgroundColor:"red"
}
}
})
</script>