VUE
Vue的基本常识
Vue的使用方式
vuejs的使用官方提供了2种方式:
- 基于脚本导入使用,下载vue.js文件,通过script标签引入到html网页。
- 基于项目构建工具来进行使用,需要安装项目构建工具,自动构建成一个独立的项目。
目前官方推荐的项目构建工具:vue-CLI,vite。

Vue调试工具Vue Devtools 谷歌浏览器插件
官网地址:https://v3.cn.vuejs.org/guide/installation.html#%E5%8F%91%E5%B8%83%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
Vue的M-V-VM思想
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,是一种代码分工思想来的。
Model 指代的就是vue对象的data选项里面的数据。这里的数据要显示到HTML页面中。
View 指代的就是vue中数据要显示的HTML页面,也称之为“视图模板” 。
ViewModel 指代的是vue.js中我们编写代码时的创建vue实例对象vm了,它是vue.js的核心,负责连接 View 和 Model,保证视图和数据的一致性,所以前面代码中,data选项里面的数据被显示中p标签中就是vm对象自动完成的。vm对象会时刻的监控View和Model的变化,并保持双方数据的一致性!!!有时候,这个特性也叫双向数据绑定
ViewModel的创建模式
<script>
window.onload = function () {
let vm = Vue.createApp({
data() {
return {
test: "111"
}
},
methods() {
},
components: {}
}).mount("#app1")
console.log(vm);
console.log(vm.num);
console.log(vm.$data.num);
console.log(vm.$el); // vm对象控制的内容范围
console.log(vm.$el.parentElement); // vm对象本身绑定的标签元素
console.log(vm.$refs);
console.log(vm.$refs.p3);
vm.$refs.p3.style["background-color"] = "red";
}
</script>
Vue的常用指令
指令 (Directives) 是带有“v-”前缀的特殊属性,由vue提供的。每一个指令在vue中都有固定的作用。
在vue中提供了很多指令,常用的有:{{变量名}},v-if、v-model、v-for、v-html、@事件名或:属性名等等。
指令会在vm对象的data选项数据发生变化时,会同时改变元素中的其控制的内容或属性。
因为vue的历史版本原因,所以有一部分指令都有两种写法:
| vue1.x | vue2.x以后 | 描述 |
|---|---|---|
| v-html | v-html | 输出html内容到双标签中 |
| v-text="普通文本" | {{普通文本}} | 输出纯文本内容到双标签中 |
| v-bind:属性名 | :属性名 | 把属性中的内容当成vue变量进行输出 |
| v-on:事件名 | @事件名 | 绑定事件操作 |
Vue属性操作
vm.$data
1. createApp中的data选项,传递到vm对象内部时,已经变成了使用Proxy对象代理的属性,可以通过`vm.$data`来查询。
vm.$el
2. vm对象在经过调用mount方法绑定HTML标签以后,这个标签代表的就是当前vm对象的可控范围,可以通过`vm.$el`属性来查询,
通过要获取绑定vm的HTML元素,可以通过`vm.$el.parentElement`来获取。
vm.$refs # 通过$refs来抓取
3. vm对象提供$refs可以让我们开发者直接在vm控制的视图范围,使用`ref`属性绑定任意元素,并在`vm.$refs`中获取。
vm.$refs.p3 则表示获取视图代码中的 `ref="p3"`的标签。
$refs只能作用一次,有多个对象只有第一个生效
--------------标签属性--------------
<标签名 :标签属性="data变量名"></标签名>
<input :type="type" :checked="checked"></input>
<p :title="str1">{{ str1 }}</p> <!-- 也可以使用v-html显示双标签的内容,{{ }} 是简写 -->
<a :href="url2">淘宝</a>
<a v-bind:href="url1">百度</a> <!-- v-bind是vue1.x版本的写法 -->
渲染后标签数据如下🔽
<input type="checkbox">
<p title="111">111</p><!-- 也可以使用v-html显示双标签的内容,{{ }} 是简写 -->
<a href="http://www.baidu2.com">百度2</a>
<a href="http://www.baidu.com">百度</a><!-- v-bind是vue1.x版本的写法 --></div>
显示/隐藏密码练习代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="assets/vue.global.3.2.20.js"></script>
</head>
<body>
<div id="app">
密码:<input :type="input_type"><button @click="show_password">{{btn_text}}</button>
</div>
<script>
var vm = Vue.createApp({
data(){
return {
input_type: "password",
btn_text: "显示密码",
}
},
methods:{
show_password(){
// 显示密码
if(this.input_type === "password"){
this.input_type = "text";
this.btn_text = "隐藏密码";
}else{
this.input_type = "password";
this.btn_text = "显示密码";
}
}
}
}).mount("#app");
</script>
</body>
</html>
Vue显示数据
- 在双标签中显示纯文本数据一般通过{{ }}来完成数据显示,双花括号中还可以支持js表达式和符合js语法的代码,例如函数调用.
<h1>{{message}}</h1> - 如果双标签的内容要显示的数据包含html代码,则使用v-html来完成
<h1 v-html="message"></h1>和上面纯文本不同的是,v-html是以标签形式显示 - 在表单输入框中显示数据要使用v-model来完成数据显示
整个HTML网页组织起来就是DOM树形结构,那么vue在视图模板的时候,采用了虚拟DOM方式来展示数据的。
Vue事件绑定
基本写法
<标签名 @click="num+=5">按钮</标签名>
<标签名 @click="方法名">按钮</标签名>
<标签名 @click="方法名(参数1,参数2,....)">按钮</标签名>
| vue写法 | 原生javascript写法 | 描述 |
|---|---|---|
| @click | onclick | 鼠标点击事件 |
| @dblclick | ondblclick | 鼠标双击事件 |
| @submit | onsubmit | 表单提交事件 |
| @focus | onfocus | 获取焦点事件 |
| @blur | onblur | 失去焦点事件 |
| @change | onchange | 值发生改变事件 |
| .... | ... | ... |
事件写在Vue的methods方法
商品增加减少数量
步骤:
- 给vue对象添加操作数据的方法
- 在标签中使用指令调用操作数据的方法
<body>
<div id="app">
<button @click="sub">-</button>
<input type="text" v-model.number="num" size="2" @change="check_num">
<button @click="num++">+</button>
</div>
<script>
var vm = Vue.createApp({
data(){
return {
num: 0,
}
},
methods: { #定义了sub和check_num事件
sub(){
if(this.num<=0){
return false;
}
this.num--;
},
check_num(){
if(this.num<0){
this.num = 0;
}
}
}
}).mount("#app");
</script>
</body>
表单的数据校验练习示例
<body>
<div id="app">
登录账号:<input type="text" placeholder="请输入账号!" v-model="username" @blur="check_username" @focus="clear_tips('username_tip')">
<span class="tips" ref="username_tip"></span><br>
登录密码:<input type="password" placeholder="请输入密码!" v-model="password" @blur="check_password" @focus="clear_tips('password_tip')">
<span class="tips" ref="password_tip"></span><br>
确认密码:<input type="password" placeholder="请输入确认密码!" v-model="password2" @blur="check_password2" @focus="clear_tips('password2_tip')">
<span class="tips" ref="password2_tip"></span><br>
<input type="submit" value="注册" @click="submit_form">
</div>
<script>
var vm = Vue.createApp({
data(){
return {
username: "root",
password: "",
password2: "",
}
},
methods: {
check_username(){
if(this.username.length < 4 || this.username.length > 12){
this.$refs.username_tip.innerHTML = "请输入4-12个字符长度的登录账号!";
return true;
}
},
clear_tips(name){ # 还可以进行传参
this.$refs[name].innerHTML = ""
},
check_password(){
if(this.password.length<6 || this.password.length>16){
this.$refs.password_tip.innerHTML = "请输入6-16个字符长度的登录密码!";
return true;
}
},
check_password2(){
// 验证密码与确认密码是否一致
if(this.password !== this.password2){
this.$refs.password2_tip.innerHTML = "登录密码与确认密码必须一致!";
return true;
}
},
submit_form(){
if (this.check_username() || this.check_password() || this.check_password2() ){
console.log("验证失败!无法提交数据");
return false;
}
}
}
}).mount("#app");
</script>
</body>
Vue操作样式
- 控制标签class类名
<h1 :class="值">元素</h1> # 值可以是变量名、对象、对象的变量名、数组、数组变量名
一共有5种写法
data(){
return {
cls1: "p1",
b1: true,
b2: true,
p_cls1: {p1: true,p2: false},
cls2: {p2: true,},
cls3: {p1: true,},
arr: [{p1: true},{p2: true},]
}
},
----------------------------------
<p>用法1::class属性值是一个class类名的变量</p>
<p :class="cls1">一段文本信息</p>
<p>用法2::class属性值是一个json对象</p>
<p :class="{p1: b1, p2: b2}">一段文本信息</p>
<p>用法3::class属性值是一个对象变量名</p>
<p :class="p_cls1">一段文本信息</p>
<p>用法4::class属性值是一个数组,数组的成员是data中声明的用于控制样式的json对象</p>
<p :class="[cls2,cls3]">一段文本信息</p>
<hr>
<p>用法5: :class属性值时一个数组变量名</p>
<p :class="arr">一段文本信息</p>
注意:
:class属性在同一个标签中,只能出现一次,后面出现的:class属性会被vue忽略掉,但是:class可以和class属性组合使用,class也只能在同一个标签中出现一次
<p class="p1" :class="cls2" :class="cls3"> 一段文本信息</p> 这里的cls3会被忽略掉
但是下面2种形式是可以的.
<p class="p1" :class="cls2" >
<p class="p1" :class="[cls2,cls3]" >
- 控制style样式 (很少用,一个规范不允许,另一个就是代码不好维护。)
代码示例如下
<div id="app">
<p>用法1::style的值是一个json对象</p>
<p :style="{'font-size': size, color: col1}">一段文本信息</p>
<hr>
<p>用法2::style的值是一个对象变量名</p>
<p :style="sty1">一段文本信息</p>
<hr>
<p>用法3::style的值是一个数组,数组的成员是样式组成的对象</p>
<p :style="[sty2, sty3]"></p>
<p>用法4::style的值是一个数组变量名</p>
<p :style="sty_list"></p>
</div>
------------------------------
<script>
var vm = Vue.createApp({
data(){
return {
sty1: {
"text-align": "center",
"color": "yellow",
"background-color": "red",
},
sty2: {
"width": '150px',
"height": '150px',
},
sty3: {
"background-color": "red",
},
sty_list: [
obj,
{
"width": '150px',
"height": '150px',
},
]
}
},
}).mount("#app");
</script>
选项卡特效示例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="assets/vue.global.3.2.20.js"></script>
<style>
p{
padding: 0;
margin: 0;
}
.title-list span{
display: inline-block; /* 设置元素的显示模式:行级块状元素 */
height: 60px;
line-height: 60px;
width: 120px;
background-color: #bbb;
text-align: center;
cursor: pointer;
}
.title-list .activate{
background-color: yellow;
}
.content-list .content{
background-color: yellow;
display: none;
width: 370px;
height: 280px;
}
.content-list .current{
display: block;
}
</style>
</head>
<body>
<div id="optioncard">
<div class="title-list">
<span :class="{activate: index === 0}" @click="index=0">国内新闻</span>
<span :class="{activate: index === 1}" @click="index=1">国际新闻</span>
<span :class="{activate: index === 2}" @click="index=2">银河新闻</span>
</div>
<div class="content-list">
<div class="content" :class="{current: index === 0}">
<p>国内新闻列表</p>
<p>国内新闻列表</p>
<p>国内新闻列表</p>
<p>国内新闻列表</p>
<p>国内新闻列表</p>
</div>
<div class="content" :class="{current: index === 1}">
<p>国际新闻列表</p>
<p>国际新闻列表</p>
<p>国际新闻列表</p>
<p>国际新闻列表</p>
<p>国际新闻列表</p>
</div>
<div class="content" :class="{current: index === 2}">
<p>银河新闻列表</p>
<p>银河新闻列表</p>
<p>银河新闻列表</p>
<p>银河新闻列表</p>
<p>银河新闻列表</p>
</div>
</div>
</div>
<script>
var vm = Vue.createApp({
data(){
return {
index: 0,
}
},
methods: {
}
}).mount("#optioncard")
</script>
</body>
</html>
Vue条件渲染
- vue中提供了两个指令可以用于判断是否要显示元素,分别是v-if和v-show。
前者是渲染前作判断,如果不显示,则不会出现在html源码中
后者只是用display属性
<div id="app">
<p v-if="username">欢迎回到xx网站,尊敬的{{username}}!</p>
<p v-else>欢迎访问xx网站,尊敬的游客!</p>
<p v-if="level === 0" class="l0">您是vip会员!</p>
<p v-else-if="level === 1" class="l1">您是svip会员!</p>
<p v-else-if="level === 2" class="l2">您是mvip会员!</p>
<p v-else-if="level === 3" class="l3">您是msvip会员!</p>
<p v-else>您是签到会员!</p>
</div>
- vue列表渲染指令 通过v-for指令可以将一组数据渲染到页面中,数据可以是数组或者对象
v-for的形参
<div v-for="(item, index) in items"></div>
<div v-for="(value, key) in object"></div>
<div v-for="(value, name, index) in object"></div>
代码示例
数据是数组:
<ul>
<!--book是列表的每一个元素-->
<li v-for="book in book_list">{{book.title}}</li>
</ul>
<ul>
<!--book是列表的每一个元素,index是每个元素的下标-->
<li v-for="(book, index) in book_list">第{{ index+1}}本图书:{{book.title}}</li>
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data:{
book_list:[
{"id":1,"title":"图书名称1","price":200},
{"id":2,"title":"图书名称2","price":200},
{"id":3,"title":"图书名称3","price":200},
{"id":4,"title":"图书名称4","price":200},
]
}
})
</script>
数据是对象:
<ul>
<!--i是每一个value值-->
<li v-for="value in book">{{value}}</li>
</ul>
<ul>
<!--i是每一个value值,j是每一个键名-->
<li v-for="attr, value in book">{{attr}}:{{value}}</li>
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data(){
return {
book: {
// "attr":"value"
"id":11,
"title":"图书名称1",
"price":200
},
}
}
})
</script>
Vue对象以及对象的API
所谓的选项API就是在实例化vm对象时,往createApp中传递进行选项参数,例如,我们已经使用过的data或者methods就是选项api。
过滤器
Vue3.0已经被淘汰了过滤器这个选项,可以在methods里进行自定义函数实现过滤
代码示例 书本数量不能小于0
<body>
<div id="app">
<table class="table">
<tr>
<th>序号</th>
<th>商品名</th>
<th>价格</th>
<th>购买数量</th>
<th>单品统计</th>
</tr>
<tr v-for="(goods, key) in goods_list" :class="{bg: goods.price>100}">
<td>{{key+1}}</td>
<td>{{goods.name}}</td>
<td>{{goods.price}}</td>
<td>
<button @click="sub(goods)">-</button>
<input type="text" size="1" v-model="goods.num">
<button @click="goods.num+=10">+</button>
</td>
<td></td>
</tr>
</table>
</div>
<script>
var vm = Vue.createApp({
data(){
return {
goods_list: [
{"name":"python入门","price":150, num: 0},
{"name":"python进阶","price":100, num: 0},
{"name":"python高级","price":75, num: 0},
{"name":"python研究","price":60, num: 0},
{"name":"python放弃","price":110, num: 0},
]
}
},
methods:{
sub(goods){
goods.num-=10;
if(goods.num<0){
goods.num = 0;
}
}
}
}).mount("#app")
</script>
</body>
计算和监听属性
- 计算属性,
是vue提供给我们开发者用于编写代码时保存计算出新的数据结果的变量。主要通过computed选项进行声明的。
<body>
<div id="app">
<input type="text" size="1" v-model.number="num1">+
<input type="text" size="1" v-model.number="num2">={{result}}
</div>
<script>
var vm = Vue.createApp({
data(){
return {
num1: 10,
num2: 10,
}
},
computed: { // 计算属性选项API,里面的成员就是一个属性方法,用于保存在vm中其他变量的计算结果
result(){
return this.num1+ this.num2
}
}
}).mount("#app")
</script>
</body>
- 侦听属性
侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。
侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化前的数据值,第二个是变化后的数据值。
主要通过watch选项进行声明的。
div id="app1">
<label for="user">输入账号</label>
<input type="text" id="user" ref="username" v-model="username">
</div>
<script>
let vm = Vue.createApp({
data() {
return {
username:""
}
},
watch:{
// 侦听data中的username
username(new_data, old_data){
console.log(new_data,new_data.length)
if (new_data.length<6){this.$refs.username.style.border="1px solid red"}
else{this.$refs.username.style.border="1px solid black"}
}
}
}).mount("#app1")
</script>
当然用事件绑定实现这个功能 为了效果明显css设置一下,不要外边框颜色input{outline: None;}
<div id="app1">
<label for="user">输入账号</label>
<input type="text" id="user" ref="username" v-model="username" @keypress="user_listen(username)">
</div>
<script>
let vm = Vue.createApp({
data() {
return {
username: ""
}
},
methods:{
user_listen(username){
if (username.length < 6) {
console.log(username)
this.$refs.username.style.border = "1px solid red"
} else {
console.log(">6")
this.$refs.username.style.border = "1px solid black"
}
}
},
// watch: {
// // 侦听data中的username
// username(new_data, old_data) {
// console.log(new_data, new_data.length)
// if (new_data.length < 6) {
// this.$refs.username.style.border = "1px solid red"
// } else {
// this.$refs.username.style.border = "1px solid black"
// }
// }
// }
}).mount("#app1")
</script>
生命周期
每个vm对象在创建时都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行一些叫做生命周期的的钩子函数,我们可以使用这些函数,在对象创建的不同时间阶段加上我们需要的自动执行代码,就实现特定的功能。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="assets/vue.global.3.2.20.js"></script>
</head>
<body>
<div id="app">
<p ref="p1">{{message}}</p>
<input type="text" v-model="message">
</div>
<script>
var vm = Vue.createApp({
data(){
return {
message: "hello",
}
},
beforeCreate(){
// 当前函数执行时,vm还没有初始化完成。
console.log("beforeCreate>>>", this.$data);
console.log("beforeCreate>>>", this.$el);
console.log("beforeCreate>>>", this.$refs);
},
created(){
// 当前函数执行时,vm对象已经初始化完成
console.log("created>>> $data=", this.$data); // 此时data选项中的数据已经被注入到vm对象中
console.log("created>>> $el=", this.$el);
console.log("created>>> $refs=", this.$refs);
// 在开发中,我们可以在这个函数中进行初始化数据相关的操作,例如:使用ajax从服务器中读取数据,并赋值给data
},
beforeMount(){
// 已经把对应的vue语法的变量替换成了html内容了,但是并没有挂载到el标签的内容中
console.log("beforeMount>>> $el=", this.$el);
console.log("beforeMount>>> template=", this.$options.template);
console.log("beforeMount>>> $refs=", this.$refs);
},
mounted(){
// vue生成的HTML内容已经挂载到了$el属性中
console.log("mounted>>>", this.$el);
console.log("mounted>>>", this.$refs);
},
beforeUpdate(){
// 变量更新前,data选项中的数据发生了改变,但是没有重新生成虚拟DOM,所以HTML中的变量值没有被同步
console.log("beforeUpdate>>>", this.$data);
console.log("beforeUpdate>>>", this.$el.parentElement.innerHTML);
// 修改数据前,判断本次修改是否合法?发送ajax,
},
updated(){
// 变量更新后,html内容已经与data选项中的数据同步了,因为重新生成了虚拟DOM
console.log("updated>>>", this.$el.parentElement.innerHTML);
// 修改数据后,发送ajax,同步数据库
}
}).mount("#app")
</script>
</body>
</html>
在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。
mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。
另一个就是created,这个阶段就是在 vue对象创建以后,把ajax请求后端数据的代码放进 created
指令修饰符
指令修饰符,用于编写在vue执行之后的补充符号,作用是增强当前指令或给当前指令进行功能的调整的。
v-model的指令修饰符。
v-model.trim 用于去除字符串两边的空白字符,常用于密码
v-model.lazy 用于减少触发watch侦听选项的频率,从原来的input输入事件的侦听切换成了change值改变事件的监听
v-model.number 表示把变量作为数值来进行转换提取,能转的都会转换
常用的修饰符
.stop - 调用 event.stopPropagation(),禁止事件冒泡。
.prevent - 调用 event.preventDefault(),阻止事件默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器