1.什么是vue?
三大框架:react angule vue
官网:Vue.js
作者:尤雨溪
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。(Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:)
vue全家桶:vue+vue Cli+ vue Router + vuex +axios
版本:vue2(老项目) vue3(新项目)
而Vue又有那些特点呢?
-
单页面应用
-
轻量级的框架
-
双向数据绑定
-
指令
-
组件化
-
客户端路由
-
状态管理
缺点:
-
单页面应用
-
SEO不友好
-
兼容性(IE9以上)【因为 vue 使用了 ES5 中 Object.defineProperty () 这个属性,该方法第一个被实现是在 ie8 中,但是存在诸多限制:只能在DOM对象上使用这个方法,而且只能创建访问器属性(数据属性无法访问)。 因此在 ie8 以及以下的浏览器,vue程序无法运行。】
在使用 Vue 时,可以在浏览器上安装 Vue Devtools。它允许你在一个更友好的界面中审查和调试 Vue 应用。可以在浏览器扩展中添加,并在详细信息里面打开访问url的选项,安装成功后,在一个引入vue.js的html页面中打开开发者工具栏就能得到以下页面:
如果看到这里证明你的vue扩展功能安装成功了。
2.基础使用
1.环境
生产环境:
开发结束,项目上线 压缩 速度快
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
开发环境:
正常开发中 未压缩 用于学习和开发
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
2.使用
1.引入Vue框架
2.在html中定义一个html的挂载元素
3.初始化Vue
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 第一步:引入vue框架 -->
<script src="./js/vue.js"></script>
<style>
.box {
font-size: 27px;
}
</style>
</head>
<body>
<!-- 第二步:定义一个html挂载元素 -->
<!-- {{}} Mustache 插值表达式-->
<div id="app">
{{str}} {{num}}
<div class="box">{{str}}</div>
{{num+1}}
<br> {{flag?className:str}}
</div>
<script>
// 第三步:初始vue
let vm = new Vue({
el: "#app", //指定vue对象的生效范围
data: { //存放数据的地方
str: "hello Vue",
className: "box",
num: 1000,
flag: true,
}
})
// console.log(vm);
let num1 = vm.num;
setInterval(() => {
num1++;
vm.num = num1;
}, 1000);
// 1.在data中添加内容,就相当于为vue实例添加属性
// 2.在页面中可以直接使用插值表达式来显示data中的内容 {{变量名}}
// 3.data中的数据发生变化,页面会自动改变
</script>
</body>
</html>
注意点:
el挂载节点 将这个vue实例和作用节点范围关联起来
data数据对象 节点范围内使用到的数据
-
data中的数据可以在模板中通过插值表达式中显示{{}}
-
data中添加内容,就相当于为vue实例添加属性
-
data中的数据发生变化,页面会自动改变
总结:
vue生效,就必须创建一个vue实例,而且需要设置配置对象。
app容器中的代码依然符合html规范,不过是增加一些vue语法。
app容器里的代码被称为vue模板。
vue实例和容器是一一对应的。
真实开发中只有一个vue实例,并且会配合组件一块使用。
{{}}中可以书写js表达式,并且可以自动读取到data里对应的值。
扩展:
// 第一种写法
let vm = new Vue({
el: "#app",
// data: {
// num: 2023,
// }
data() {
return {
num: 02023,
}
}
})
// 第二种写法
let vm = new Vue({
data() {
return {
num: 2023,
}
}
});
vm.$mount('#app');
data和el的两种写法:
1.el的两种写法:
(1)new Vue的时候配置el属性
(2)先创建实例,在后面通过$mount()方法绑定
2.data的两种写法:
(1)对象形式
(2)函数形式
注意:
由vue管理的函数,不能写箭头函数,一旦写了箭头函数,this指向就改变。
4.常用的指令
1.指令的概念
指令是vue给标签增加的新属性,以v-开头。
语法:
<标签 v-指令名=“变量/表达式”></标签>
2.常用的指令
1.v-text
类似于innerText.
作用:向其所在的节点中渲染文本内容。
会覆盖节点中原有的内容。
<p v-text="text">{{str}}</p>
<p v-text="text"></p>
2.v-html
解析HTML字符串,类似于innerHTML.
作用:向其所在的节点中渲染html结构内容。
会覆盖节点中原有的内容。
<p v-html="html"></p>
<p v-html="html">{{str}}</p>
<p v-html="str">{{html}}</p>
3.v-bind
作用:让vue可以识别HTML原有的属性支持,渲染变量或表达式,单向的数据绑定,数据是data流向页面。
语法:
<标签 v-bind:HTML原有的属性=“变量/表达式”></标签>
简写
<标签 :HTML原有的属性=“变量/表达式”></标签>
<p v-bind:class="num<15?className:className1">{{str}}</p>
<p :class="num<15?className:className1">{{str}}</p>
<img :src="imgSrc" alt="">
<a :href="url">跳转</a>
4.v-if
作用:条件渲染 (条件不满足,节点不存在)
语法:
<标签 v-if="变量/表达式"></标签>
<标签 v-else-if="变量/表达式"></标签>
<标签 v-else="变量/表达式"></标签>
注意:必须紧邻着写。
<p v-if="num<12">上午</p>
<p v-else-if="num<18">下午</p>
<p v-else>晚上</p>
<h1 v-if="flag">{{html}}</h1>
5.v-show
作用:条件渲染 (条件不满足,节点隐藏) display
语法:
<标签 v-show="变量/表达式"></标签>
<p v-show="flag">{{html}}</p>
v-if和v-show的区别:
v-show无论条件成立不成立,节点都存在。
v-if条件成立,节点存在,条件不成立,节点不存在。
需要反复展示的内容使用v-show,渲染次数少的用v-if。
6.v-for
作用:渲染列表数据
语法:
<标签 v-for="值 in 数组"></标签>
<标签 v-for="(值,索引) in 数组"></标签>
<标签 v-for="(值,键) in 对象"></标签>
代码示例:
<!-- <div v-for="(item,index) in arr">
{{item}}-----{{index}}
</div> -->
<!-- <ul>
<template v-for="item in arr">
<li>{{item}}</li>
</template>
</ul> -->
<!-- <div v-for="(item,index) in arr" :key="index">
{{item}}
</div> -->
<ul>
<template v-for="(item,index) in bookList">
<li :key="index">图书:{{item.bookName}},作者:{{item.author}}</li>
</template>
</ul>
注意:双层嵌套,标识符不能重复。
v-if和v-for一般不在一起使用。当他们处于同一个节点时,v-for的优先级比v-if要高(vue2)。
【这句话可以理解为在同时使用中v-for执行之前v-if是取不到相关的变量,也就无法运行】
添加key属性(
7.v-once
作用:只能绑定一次。数据变化,页面不会更新。
【这个打开开发工具栏,点击Vue调试v-once绑定的事件的时候,页面中的值是不会发生改变的】
使用:
1.v-once所在节点在初次动态渲染后,就视为静态内容。
2.以后数据的改变就不会引起v-once所在的结构的更新,用于性能优化。
语法:
<标签 v-once>{{}}</标签>
8.v-on
简写为:@
1.不传参
语法:
<标签 v-on:事件=“事件函数名”></标签>
key的值要保证是唯一);
代码示例:
<div id="app">
{{str}}
<p v-once>{{str}}</p>
<button v-on:click="send">发送</button>
<button @click="send">发送</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
str: "vue指令",
},
methods: { //对象
事件函数名() {
},
send() {
alert("发送成功");
}
}
})
</script>
2.传参
语法:
<标签 v-on:事件=“事件函数名(实参)”></标签>
代码示例:
<div id="app">
{{str}}
<button @click="send('发送成功')">发送</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
str: "vue指令",
},
methods: { //对象
// 事件函数(形参) {
// },
send(str) {
alert(str)
}
}
})
</script>
3.事件对象
语法:
<标签 v-on:事件=“事件函数名(实参,$event)”></标签>
代码示例:
<div id="app">
<!-- <button @click="send($event)">发送</button> -->
<ul @click="getLi('liiiii',$event)">
<template v-for="(item,index) in arr">
<li :key="index">{{item}}</li>
</template>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
str: "vue指令",
arr: [1, 2, 3, 4, 5, 6, 7, 8]
},
methods: { //对象
getLi(str, e) {
console.log(str);
console.log(e.target.innerHTML);
}
}
})
</script>
点击table栏切换在Vue中也有不同的写法
<div id="app">
<button :class="index==0?'bg':''" @click="index=0">盒子1</button>
<button :class="index==1?'bg':''" @click="index=1">盒子2</button>
<button :class="index==2?'bg':''" @click="index=2">盒子3</button>
<div class="box">
<!-- v-show后面跟判断条件 true 显示 false 不显示 -->
<div v-show="index==0">内容1</div>
<div v-show="index==1">内容2</div>
<div v-show="index==2">内容3</div>
</div>
</div>
<script>
const vm = new Vue({
el: " #app ",
data() {
return {
index: 0
}
},
methods: {
// change(num) {
// // console.log(this);
// this.index = num;
// }
},
})
</script>
4.事件简写
如果是一些简单的事件处理可以简写。
代码示例:【购物车的加减按钮】
<div id="app">
<button @click="num--">-</button>
<span>{{num=num<1?1:num}}</span>
<button @click="num++">+</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
num: 1
},
// methods: {
// add() {
// this.num--
// },
// sum() {
// this.num++
// },
// }
})
5.事件修饰符
辅助我们做一些事件的处理。
语法:
<标签 @事件名.修饰符=“事件函数”></标签>
<标签 @事件名.修饰符.修饰符=“事件函数”></标签>
常用的修饰符:
- .stop 阻止事件冒泡
event.stopPropagation()
。 - .prevent 阻止默认行为 event.preventDefault()
- .capture 使用事件的捕获模式
- .self 只有event.target是当前的操作元素才触发事件
- .once 事件只触发一次
- .passive 事件的默认行为立即执行,无需等待时间回调执行完毕
- .{keyCode | keyAlias} 只当事件是从特定键触发时才触发回调
<div id="app">
<!-- 只触发一次 -->
<div class="box" @click.once="box">
<!-- 阻止冒泡 -->
<div class="box1" @click.stop.once="box1">
<!-- 阻止默认行为和冒泡 -->
<a href="./01-vue基础-指令.html" @click.prevent.stop>调整</a>
</div>
</div>
<div class="box" @click="fn1">
<!-- 阻止冒泡 -->
<div class="box1" @click.self="fn2">
<!-- 阻止默认行为和冒泡 -->
<button @click="fn3">调整</button>
</div>
</div>
<!-- 键修饰符,键别名 -->
<button @keyup.enter="fun">发动</button>
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
</div>
<script>
const vm = new Vue({
el: "#app",
data: {},
methods: {
box() {
console.log(111);
},
box1() {
console.log(222);
},
fn1() {
console.log(1);
},
fn2() {
console.log(2);
},
fn3() {
console.log(3);
},
fun() {
console.log(4);
}
},
})
</script>
5.响应式原理
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
简单理解:
data里面的数据都会添加getter和setter两个方法,然后watcher会监听这些变化,当data里的数据被访问就会触发get方法,当data里的数据被修改就会触发set方法。修改数据,就会进行虚拟DOM比较,重新渲染数据。
1.数组和对象的更新问题
1.问题:
data里面的某个数据是对象的时候:
-
我们使用原来的方法新增属性,页面不会被响应。 this.obj.sex = "男";
-
删除某个属性的时候,页面也不会被响应。 delete this.obj.uname;
data里面的某个数据是数组的时候:
-
通过索引添加数据,或修改值的时候,页面也不会被响应。
2.原因:
上述这些修改的数据并没有setter和getter,不会被watch监听到,所以页面不会响应。
3.解决:
(1)对象:
语法:
this.$set(对象名,属性名,属性值)
作用:给对象新增属性或者修改属性。
this.$set(this.obj, "sex", "男");
this.$delete(对象名,属性名)
作用:给对象删除属性。
this.$delete(this.obj, "uname");
(2)数组:
语法:
this.$set(数组名,索引,值)
作用:给数组新增数据或者修改数据。
this.$set(this.arr, 4, 6);
this.$delete(数组名,索引)
作用:给数组删除数据。
this.$delete(this.arr, 3);
同时可以使用数组自带的api方法:push、pop、shift、unshift......
推荐使用自带的方法!!!·
6.双向绑定
核心指令:v-model
原理:
<div id="app">
<input type="text" :value="uname" @input="change"> <br> {{uname}}
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
uname: "这个是默认的值",
},
methods: {
change(e) {
this.uname = e.target.value
}
}
})
</script>
表单修饰符:
- .lazy input失焦的时候触发
- .number 把输入的数字变成number类型
- .trim 去除收尾的空格
代码示例:
<div id="app">
<!-- 文本框 -->
<input type="text" v-model="uname"> <br> {{uname}}
<!-- 单选 -->
<input type="radio" name="sex" id="" v-model="value" value="男">男
<input type="radio" name="sex" id="" v-model="value" value="女">女
<!-- 多选 -->
<input type="checkbox" name="fruits" id="" value="苹果" v-model="arr">苹果
<input type="checkbox" name="fruits" id="" value="火龙果" v-model="arr">火龙果
<input type="checkbox" name="fruits" id="" value="香蕉" v-model="arr">香蕉
<input type="checkbox" name="fruits" id="" value="西瓜" v-model="arr">西瓜
<!-- 文本域 -->
<textarea name="" id="" cols="30" rows="10" v-model="text"></textarea>{{text}}
<!-- 下拉框 -->
<select name="" id="" v-model="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
</select
<input v-model.lazy="msg">{{msg}}
<input v-model.trim="msg">
<input type="text" v-model.number="num">
<input type="text" v-model.trim="num">
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
msg: "message",
uname: "这个是个默认的值",
// value: "男",
arr: ["苹果"],
text: "这是一个文本域",
city: "北京",
num: "123",
},
methods: {
}
})
</script>