Vue2学习文档
文章目录
1. Vue简介
P1 课程简介
空
P2 Vue技术
虚拟dom通过diff算法比较差异实现渲染复用
P3 官网指南
学习-Cookbook
提供编程技巧(让代码更优雅)
资源列表-Awesome Vue
官方推荐认可的Vue第三方库(如能用来制作一个报表)
P4 开发环境
引入Vue.js后,可以在浏览器-console中输入Vue.config查看Vue API(全局配置 )
2. 简单例子
P5 Hello 案例
{{}}:Vue设计的插值语法(获取Vue实例-data里的值)
root容器里的代码被称为【Vue模板】
模板解析流程:
- 先有容器,然后有实例
- 实例拿到对应id容器
- 实例解析(看有没有设计的特殊语法)
- 把解析完后的Dom树导出替换容器
P6 分析Hello
容器和实例是一一对应的
<div id='root'></div>
new Vue({
el:'#root',
……
})
},
‘{{}}’里必须写js表达式
3. 数据绑定
P7 模板语法
插值语法:解析标签体内容
<div>{{xxx}}</div>
指令语法:解析标签属性(属性、内容、事件)V-XXX
<a v-bind :herf='xxx'>点击</a>
P8 数据绑定
v-modal只能应用在表单类元素(输入类元素)上
P9 el和data两写法
- el
el:‘#root’ 和v.KaTeX parse error: Expected 'EOF', got '#' at position 8: mount('#̲root')效果相同(mount是vue实例原型构造器的方法)
- data
- 对象式
data:{
name:'xxx'
}
- 函数式(以后用组件时必须用这种,对象式会报错)
data:function(){
return{
name:'xxx'
}
}
//简写成(不能写箭头函数,不然this指向windows)
data(){
return{
name:'xxx'
}
}
4. 数据代理(JS知识补充)
P10 MVVM
如图所示:
代码:Vue实例把Data和View进行连接
data里的数据最终出现在vm上,而模板{{}}或v-xxx可以从vm中获取属性值
<h1>{{$emit}}</h1>
//$emit是vm原型链上所有的属性
P11 defineProperty
为什么console.log()里面的属性不直接显示,原因:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iWiJHTsz-1652602773252)(Images/image-20210816165528539.png)]
给对象添加属性,具体语法如图:
第一个参数是对象名,第二个参数是属性名,然后是在defineProperty对属性的内置操作方法中写表达式
第三个参数中get():有人读取属性时,放回属性值;set():有人修改属性时,用改方法设置修改值
P12 数据代理
P13 Vue中的数据代理
vm._data === data
data(){
return {
data:'xxx'
}
}
但为什么vm._data===data呢?这个就不细讲了,只要知道是数据劫持即可
5. 事件绑定
P14 事件处理
''里的模板只能用vm
注:所有vm里的方法有不要写成箭头函数,不然this指向windos
如何保持事件原有参数(用关键词传参)
注:写在methods里的方法不会做数据代理,如果写在data中会多做一次数据代理
P15 修饰符
<a href='xxx' @click.prevent='showinfo'/>
prevent会组织默认事件,如阻止a的跳转
不常用,具体细节看视频吧
P16 键盘事件
触发分为两种:@keyup和@keydown
有几个按键比较特殊,具体看视频
P17 事件总结
修饰符可以连写,先后同时生效
<a href='xxx'@click.prevent.stop='xxx'/>
@click='xxx'
=== @click='xxx($event)'
6. 计算属性
P18 姓名案例
每次data改变,都会引起vue的重新渲染
所以如果使用方法替代计算属性的话,每次渲染都会return最新值
P19 计算属性
computed有缓存机制,相对于methods来说更高效,这也是为什么要用计算属性的原因
get()只有当初始化和依赖数据发生改变时执行
computed不会像data和methods一样,直接绑定到vm上,所以{{fullName.get()}}会报错,Vue做了内部处理,{{fullName}}能默认调用get()
vm.fullname=xxx 则会调用fullname{}里的set()
P20 简写
只需要读取时可以使用简写
7. 监视属性
P21 天气案例
注:如果页面内容没变,vm数据变了,开发者工具不一定更新(实际上是变了)
P22 监视属性
watch语法如下:
key为被监控dataName,计算属性也能被监视,并提供一系列方法
也可以直接调用vm.$watch(),效果相同
P23 深度监视
- 监视多级结构的某个属性(完整写法.)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtE6RBzD-1652602773254)(Images/image-20210817141421438.png)]
- 监视多级结构的所有属性(设置deep值)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rS5fImuP-1652602773254)(Images/image-20210817141514247.png)]
P24 简写
和methods相同,只有"单纯"操作时,才能简写(不可添加deep等配置)
两种写法如下(和methods相似)
- 构造
- 实例
P25 对比(watch和computed)
一般来说能用computed的就用计算,不能的再用watch(因为官方也推荐计算,代码量少呀)
然后计算属性因为只依靠return返回值,所以不能进行一些异步操作(setTimeout),加了异步就return不到计算属性函数上
详细区别如下:
8. 样式渲染
P26 Class绑定
code
<!-- 指定单个样式变量-字符 -->
<div class="basic" :class="mood">{{name}}</div> <!-- class和:class可以共存-->
<!-- 指定多个样式变量-数组 -->
<div :class="classArr">{{name}}</div>
<div :class="['atguigu1','atguigu2']">{{name}}</div>
<div class="atguigu1 atguigu2">{{name}}</div>
<!-- 同效-感觉这方式只是为了少写代码,没啥妙用 -->
<!-- 指定多个样式变量并控制是否使用-对象 -->
<div :class="classObj">{{name}}</div>
<div :class="{atguigu1:value}">{{name}}</div>
<!-- 同效-可用这个替代部分三元 -->
<script>
const vm = new Vue({
data:{ //这三种都可以写在!!行内-更简洁,如果样式比较多可以写在data中控制
mood:'normal',
classArr:['atguigu1','atguigu2'],
classObj:{
atguigu1:false,
atguigu2:false,
},
},
})
</script>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
</style>
p:实际上这两节的内容并不实用,因为很多情况下的业务是条件渲染样式,这里实际上是各种动态指定样式变量
old
三种写法(字符串\数组\对象)
https://www.cnblogs.com/guangzhou11/p/11116378.html
实例博客
P27 Style绑定
code
<view :style="{ fontSize:fs }"/> <!-- 内联写法-指定对象的属性变量-->
<view :style="{ fontSize:prop }"/> <!-- 同上-更简洁,不走data-->
<div class="basic" :style="styleObj">{{name}}</div> <!-- 指定对象变量-->
<view :style="{ fontSize:prop,color:prop2 }"/> <!-- 同上-更简洁,不走data-->
<div :style="styleArr">{{name}}</div><!--指定对象变量-使用数组 -->
……
<script>
const vm = new Vue({
data:{
fs:'xxx'
styleObj:{
fontSize: '40px',
color:'red',
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
})
</script>
p:个人感觉这样写不优雅
实战
<view :style="styleObject"/> //指定对象变量
<view :style="{ height: meunHeight }"/> //指定对象的属性变量
computed: {
//根据当前菜单状态动态设置菜单高度
meunHeight() {
let meunHeight;
switch (this.$store.state.nowMeun) {
case "PathSelect":
meunHeight = "340rpx";
break;
case "StartNav":
meunHeight = "126rpx";
break;
}
return meunHeight;
},
//根据当前菜单高度
styleObject() {
let obj;
obj = { //这里和上面的data-styleObj差不多,只不过用computed来动态设置对象的属性
height: `calc(100vh - ${this.meunHeight} - var(--window-bottom))`,
fontSize: "13px",
};
return obj;
},
},
old
有两种(对象和数组)
注:{}要写样式对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Stmd0S01-1652602773255)(Images/image-20210817153938296.png)]
ps:class和style总结
P28 条件渲染
如图所示(v-show\v-if\v-else-if\template)
v-show控制的是dispaly,所以是高频率合适,这里写反了
9. 列表渲染
P29 基本列表
数组\对象
其他:字符串\指定次数(用的少)
P30 Key作用与原理
具体分析见视频
文字总结:
ps:如果没写key,Vue会自动帮我们使用:key=‘index’(所以只要不会破坏结构,就不用写key,减少代码量hh)
P31 过滤
Key: watch:{}中可以添加immediate:true属性使组件初始化时就调用一次监听
watch:{
keyWorud:{
immediate:true, //初始化调用
handler(val){
return xxx
}
}
}
这里时列表过滤的最优解-computed(通过输入框搜索展示列表内容)
具体还是看视频吧
P32 列表顺序
如图,强大的计算属性功能哈
10. 监视原理(JS补充)
P33 更新原理
下图的修改会失效,原因是内存变量确实改了,但是vue没监听到吼
P34 Vue监听对象
这节是对对象的监视的分析,而不是基本类型
- 错误写法
自己尝试写一个监视,但是会报错,说栈溢出(陷入死循环了)
原因:上图如果有人读取name,则调用get(),但是get()中return 的是data.name,读取data.name有需要get(),所以会陷入嵌套死循环
- 模拟Vue底层写法
- 现在简单重现下vue底层方法实现(使用了一个构造函数)
构造函数就是通过defineproperty属性传入参数data,’拷贝‘data中所有属性,而且修改和读取时不会发生循环
- 所以上面的构造函数实例obs,console.log出来就是一个带有data所有属性的方法实例
- 准备一个vm对象 ,复制obs
- 但是data还没变,然后来个连等(这样_data、data和obs就一样了)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2egK0uLA-1652602773256)(Images/image-20210818151646108.png)]
-
然后再defineproperty.set(){xxx}中添加操作就可以实现监听渲染了(不会像“错误写法”那样出现死循环)
PS:肯定又疑惑了,为什么构造的就不会像错误的那样出现死循环呢?
⭐️个人感觉是构造的get()读取和set()的内容不是同一个东西(地址)
这里的this指的是构造函数Obeserver(obj)地址;
而obj是指传入的对象地址
如上图是错误的,因为return 后面的内容会再次触发读取(主要就是看绿色是否是同一个对象属性)
- Vue真实底层
我们没有做到的内容:修改更便捷(数据代理)、多层设置
1.2.
P35 Vue.set()方法
常见错误
直接赋值student.sex不可行,原因如图-没有相关方法
正文
<h2 v-if="student.sex">性别:{{student.sex}}</h2>
<h2 >姓名:{{student.name}}</h2>
data:{
student:{
name:'tom', //没有sex属性
}
},
methods: {
addSex(){
// Vue.set(this.student,'sex','男') //Vue.set和this.$set都可以
this.$set(this.student,'sex','男')
}
}
注意:对象不能是 Vue 实例,或者 Vue 实例的根数据对象-data。
补充
关于属性不存在报错问题
<h2 >性别:{{student.sex}}</h2>
//这里不报错,因为如果属性为空的话是返回undefined,undefined在页面不显示
student:{
name:'tom',
//sex:'男'
}
P36 Vue监测数据改变的原理_数组
直接修改数组不可行
如图数组里是没有set()和get()
直接改不可行
vue对常见的数组方法封装,实现数组监听
如下图,两个方法不相同
使用set()也可以-但是一般都直接用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aXxFNrTX-1652602773257)(Images/image-20220113181824064.png)]
简写
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hm2mspAM-1652602773258)(Images/image-20220113163442213.png)]
P37 总结Vue监视数据
Vue监视数据的原理:
1. vue会监视data中所有层次的数据。
2. 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value) 或
vm.$set(target,propertyName/index,value)
3. 如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事
(1).调用原生对应的方法对数组进行更新
(2).重新解析模板,进而更新页面
4.在Vue修改数组中的某个元素一定要用如下方法:
1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
//dom
<h1>学生信息</h1>
<button @click="student.age++">年龄+1岁</button> <br/>
<button @click="addSex">添加性别属性,默认值:男</button> <br/>
<button @click="student.sex = '未知' ">修改性别</button> <br/>
<button @click="addFriend">在列表首位添加一个朋友</button> <br/>
<button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br/>
<button @click="addHobby">添加一个爱好</button> <br/>
<button @click="updateHobby">修改第一个爱好为:开车</button> <br/>
<button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
<h3>姓名:{{student.name}}</h3>
<h3>年龄:{{student.age}}</h3>
<h3 v-if="student.sex">性别:{{student.sex}}</h3>
<h3>爱好:</h3>
//data
student:{
name:'tom',
age:18,
hobby:['抽烟','喝酒','烫头'],
friends:[
{name:'jerry',age:35},
{name:'tony',age:36}
]
}
//以下就是对于监视原理这章的总结
addSex(){
// Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')
},
addFriend(){
this.student.friends.unshift({name:'jack',age:70})
},
updateFirstFriendName(){
this.student.friends[0].name = '张三'
},
addHobby(){
this.student.hobby.push('学习')
},
updateHobby(){
// this.student.hobby.splice(0,1,'开车')
// Vue.set(this.student.hobby,0,'开车')
this.$set(this.student.hobby,0,'开车')
},
removeSmoke(){
this.student.hobby = this.student.hobby.filter((h)=>{
return h !== '抽烟'
})
}
10a.表单例子
P38 收集表单数据
收集表单数据:
若:,则v-model收集的是value值,用户输入的就是value值。
若:,则v-model收集的是value值,且要给标签配置value值
若:
1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性
(1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的的就是value组成的数
备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
<form @submit.prevent="demo"><!-- 修饰符阻止默认行为-->
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
密码:<input type="password" v-model="userInfo.password"> <br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
<!-- number和.number保证输入的是数值-->
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
<br/><br/>
所属校区
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="wuhan">武汉</option>
</select>
<br/><br/>
其他信息:
<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
<button>提交</button>
</form>
data:{
userInfo:{
account:'',
password:'',
age:18,
sex:'female',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo)) //转换成json,发送请求
}
}
11. 过滤器
P39 过滤器用法
如图
全局(组件公用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5C6pRPQn-1652602773258)(Images/image-20210818163835397.png)]
userInfo.other">
阅读并接受《用户协议》
提交
data:{
userInfo:{
account:‘’,
password:‘’,
age:18,
sex:‘female’,
hobby:[],
city:‘beijing’,
other:‘’,
agree:‘’
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo)) //转换成json,发送请求
}
}
## 11. 过滤器
### P39 过滤器用法
如图
<img src="Images/image-20210818163726114.png" alt="image-20210818163726114" style="zoom:67%;" />
<img src="Images/image-20210818163745248.png" alt="image-20210818163745248" style="zoom:80%;" />
<img src="Images/image-20210818163810815.png" alt="image-20210818163810815" style="zoom:80%;" />
全局(组件公用)
[外链图片转存中...(img-5C6pRPQn-1652602773258)]
更多推荐
所有评论(0)