文章目录
1:Vue基础
1.1:认识Vue.js
Vues是动态构建用户界面的渐进式 JavaScript 框架
- 渐进式意味着你可以将Vue作为你应用的一部分嵌套其中
- Vue的核心库以及其生态系统:Core + Vue-router + Vuex
Vue特点和Web开发常见高级功能
- 解耦视图和数据
- 可复用的组件
- 前端路由技术
- 状态管理
- 虚拟DOM
Vue的MVVM
M: Model 数据模型
- 数据层
- 数据可能是固定的思数据, 更多的是来自服务器, 从网络上请求下来的数据
V: View 视图模板
- 视觉层
- 在前端开发中, 通常是DOM层
- 作用: 是给用户展示各种信息
VM: View-Model 视图模型
- 视图模型层
- 是View和Model沟通的桥梁
- 一方面实现了Data Binding (数据绑定), 讲Model的改变实时的反应到View中
- 另一方面实现了DOM Listener (DOM监听), 当DOM发生一些时间 (点击, 滚动, touch等) 时, 可以监听到, 并在需要的情况下改变对应的Data
2:Vue的基础语法
2.1:Vue模板的理解
Vue的语法分为两种:
- 插值语法(双大括号表达式)
- 指令(以 v-开头)
2.1.1插值语法
功能:
- 功能: 用于解析标签体内容
- 语法: {{xxx}} ,xxxx 会作为 js 表达式解析
总结:
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2.root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
3.root容器里的代码被称为【Vue模板】;
4.Vue实例和容器是一一对应的;
5.真实开发中只有一个Vue实例,并且会配合着组件一起使用;
6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;
7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
2.1.2:指令语法
- 功能: 解析标签属性、解析标签体内容、绑定事件
- 举例:v-bind:href = ‘xxxx’ ,xxxx 会作为 js 表达式被解析
- 说明:Vue 中有有很多的指令,此处只是用 v-bind 举个例子
2.2:数据绑定
Vue中有2种数据绑定的方式:
- 单向绑定(v-bind):数据只能从data流向页面。
- 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
备注:
- 双向绑定一般都应用在表单类元素上(如:input、select等)
- v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
2.3:el与data的两种方法
data与el的2种写法:
- el有2种写法
- (1).new Vue时候配置el属性。
- (2).先创建Vue实例,随后再通过vm.$mount(’#……’)指定el的值(更加灵活)。
- data有2种写法
- (1).对象式(之前的案例都是对象式)
- (2).函数式
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
- 一个重要的原则:
- 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
2.4:数据代理
2.4.1:回顾之前的Object.defineProperty方法
2.4.2:Vue中的数据代理
- Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处:更加方便的操作data中的数据
- 基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。
2.5 :事件处理
2.5.1:事件绑定
事件的基本使用:
- 使用v-on:xxx 或 @xxx(推荐) 绑定事件,其中xxx是事件名;
- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,不要用箭头函数!否则this就不是vm了;
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
- 默认事件形参: event,隐含属性对象: $event
- @click=“demo” 和 @click=“demo($event)” 效果一致,但后者可以传参;
2.5.2:事件修饰符
Vue中的事件修饰符:
- prevent(常用) : 阻止事件的默认行为,比如点击超链接的时候会进行页面的跳转,点击表单提交按钮时会 重新加载页面等,使用".prevent"修饰符可以阻止这些事件的发生;
- stop (常用): 停止事件冒泡 (通俗讲就是阻止事件向上级DOM元素传递)
- once(常用):事件只触发一次(常用);
- capture:使用事件的捕获模式,捕获冒泡。即有冒泡发生时,有该修饰符的dom元素会先执行,如果有多个,从外到内依次执行,然后再按自然顺序执行触发的事件;
- self:只有event.target是当前操作的元素时才触发事件,通常用于避免冒泡事件的影响;
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
- stop:
- capture:
点击按钮后:
- self:
没加self修饰符时点击按钮结果为:
添加self后:
2.6:计算属性-computed
计算属性:
- 定义:要用的属性不存在,要通过已有属性计算得来。
- 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
- get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。 - 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
这个计算属性还可以如下简写:
//简写
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
2.7:监视属性-watch:
2.7.1:普通监视属性watch的使用:
- 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
- 监视的属性必须存在,才能进行监视!!
- 监视的两种写法:
- new Vue时传入watch配置
- 通过vm.$watch监视
2.7.2:watch的方法与属性
1: handler方法
2. immediate属性 .
使用watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
监听的另一种写法
vm.$watch('firstName',{
immediate:true, //初始化时让handler调用一下
handler(newValue,oldValue){
console.log('firstName被修改了',newValue,oldValue)
}
})
3: deep属性
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,比如我们 data 里有一个person对象,当我们在输入框中输入数据改变person.name的值时,我们发现person监听函数是无效的。有时候我们就想关心这个对象中的某个属性这个时候我们可以使用字符串形式监听。这样Vue.js才会一层一层解析下去,直到遇到person属性name,然后才给name设置监听函数。
2.7.2:深度监视属性
深度监视:
- Vue中的watch默认不监测对象内部值的改变(一层)。
- 配置deep:true可以监测对象内部值改变(多层)。
- 备注:
- Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
- 使用watch时根据数据的具体结构,决定是否采用深度监视。
- 加入深度监视后:
- 使用字符串形式监听
2.7.3 computed | method | watch的区别
1:computed属性和methods区别
1、computed是响应式的,methods并非响应式。
2、 调用方式不一样,computed定义的成员像属性一样访问,methods定义的成员必须以函数形式调用。
3、computed是带缓存的,只有其引用的响应式属性发生改变时才会重新计算,而methods里的函数在每次调用时都要执行。
4、computed中的成员可以只定义一个函数作为只读属性,也可以定义get/set变成可读写属性,这点是methods中的成员做不到的
比如:我们想去时刻监控数据的变化,在视图上显示不同的结果,当然这两中方法都可以实现这种效果,这个时候用computed就比较合理了,因为computed是可缓存的,只要数据层值不改变,computed就不会去改变,而且可缓存,如果数据层的值变了,computed就会实时更新到视图层上,所以说computed是响应式的。
2:computed属性和watch区别
1、computed里属性名是自定义的,它可以监听一个或多个它所依赖的数据项;而watch一次只能监听一个属性,这个属性函数接收两个参数,一个是新值一个是旧值。
2、computed里自定义的属性不能与data里的属性重复,否则会报错;而watch里监听的属性必须是已存在的,其要么是data里的属性,要么是computed里计算出来的属性。
3、watch是允许异步操作的(访问一个API),并在我们得到最终结果前,设置中间状态。这些都是计算属性computed无法做到的。
2.8:条件渲染
-
v-if
写法:
(1).v-if=“表达式”
(2).v-else-if=“表达式”
(3).v-else=“表达式”
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。 -
v-show
写法:v-show=“表达式”
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉 -
备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
-------------------------------------------------
-------------------------------------------------
2.9:样式绑定
绑定样式:
- class样式
写法:class=“xxx” xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。 - style样式
:style="{fontSize: xxx}“其中xxx是动态值。
:style=”[a,b]"其中a、b是样式对象。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>绑定样式</title>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
</style>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br/><br/>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div> <br/><br/>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:false,
atguigu2:false,
},
styleObj:{
fontSize: '40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
methods: {
changeMood(){
const arr = ['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
},
})
</script>
</html>
2.10:列表渲染
v-for指令:
- 用于展示列表数据
- 语法:v-for="(item, index) in xxx" :key=“yyy”
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<div id="root">
<!-- 遍历数组 -->
<h2>人员列表(遍历数组)</h2>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}--{{p}}--{{index}}
</li>
</ul>
<!-- 遍历对象 -->
<h2>汽车信息(遍历对象)</h2>
<ul>
<li v-for="(value,k) of car" :key="k">
{{k}}-{{value}}--{{value}}--{{k}}
</li>
</ul>
<!-- 遍历字符串 -->
<h2>测试遍历字符串(用得少)</h2>
<ul>
<li v-for="(char,index) of str" :key="index">
{{char}}-{{index}}
</li>
</ul>
<!-- 遍历指定次数 -->
<h2>测试遍历指定次数(用得少)</h2>
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
car:{
price:'70万',
name:'奥迪A8',
color:'黑色'
},
str:'hello'
}
})
</script>
2.10.1:遍历数组
v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组。为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一 key属性。
注意由于JavaScript的限制,Vue 不能检测以下变动的数组:
- 当利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
- 当修改数组的长度时,例如:vm.items.length = newLength
那怎么能够监听到 数组 更改并能触发视图的更新呢:
- 用“变更方法”
- 用“替换数组”
变更方法,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。也就是把原来指向的引用给改变了,即改变了引用就能触发视图的更新 - Vue.set,是全局vue的一个set方法,也可以使用vm.$set实例方法,该方法时全局方法Vue.set的一个别名
2.10.2:对象遍历
可以用 v-for 来遍历一个对象(对象是个键值对).
更改对象的值,会触发视图更新,改变对象中固有的值,会渲染到视图.
vm.car.price="60万"
但是若添加一个新的,就不能更新视图了(对象中是有的,只是没有渲染到视图中)
解决方法:
- 同数组,给对象一个新的引用的指向,视图可以更新:
vm.car={name:"五菱宏光",price:"5万左右"}
- 可以通过Vue.set(object,key,value):
Vue.set(vm.car,'owner',"zjw")