Vue 基础语法(一)
1.认识Vue
Vue是一套用于构建用户界面的渐进式javascript框架。作者:evenYou 尤雨溪 vue.js,他基于标准的html、css、javascript构建,并且提供了一套声明式的,组件化的编程模式,可以帮助我们高效的开发用户界面,不论这个界面的逻辑是简单还是复杂。
渐进式:可以在项目中一点一点的来引入和使用Vue(vue-route、vueX、pinia、vue-cli等等),而不必一开始就使用vue来开发整个项目
目前前端流行的三大框架
Vue:在国内市场占有率最高的一个框架,几乎所有的前端岗位都会对vue有要求。
React:在国内外市场占有率都很高,也是作为前端必学的一个框架
Angular:入门门槛高,国内市场占有率低,不否认本身是一个极其优秀的框架
现实角度:
后端:java、Go、nodejs
前端:JS
2.如何使用Vue
Vue的本质,就是一个js库,刚开始我们不用把它想的太复杂,就把它理解成一个封装好的库就行。
使用方式:
1.cdn:<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
2.下载Vue的js文件,并且自己手动导入
3.通过npm包管理工具来使用(在webpack的时候)
4.直接通过vue cli/Vite 创建项目
2.1 cdn引入和下载引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<!-- cdn引入vue -->
<!-- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> -->
<!--
下载Vue的源码,直接打开cdn的链接
复制所有的代码,创建一个新的文件然后将代码贴进去
最后通过script标签引入本地的文件
-->
<script src="../lib/vue.js"></script>
<!-- 使用vue -->
<script>
// vue的代码
// 1. 创建app
// 这个app可以传入一个对象作为参数
const app = Vue.createApp({
// template属性可以解析html标签
template:`<h1>你好 vue3</h1>`
});
// 2. 挂载
// 把app挂载到对应的位置
// 把vue挂到id为app的div中
app.mount("#app")
</script>
</body>
</html>
3.Vue的体验
3.1 动态数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../lib/vue.js"></script>
<script>
// 创建app
const app = Vue.createApp({
// 插值语法:{{msg}}把msg中的值解析出来 展示到页面中
template: `<h1>{{msg}}---{{title}}---{{obj}}</h1>`,
// 第二个属性叫做data,这个data是固定的vue规定好的用来声明你要展示/处理的一些数据
// 如果你想展示return的对象里面的数据,就得使用对应的语法{{}}---mustache语法
data:function() {
return {
title: "你好 vue3",
msg: "广州笑笑",
obj: {
name: "dai",
address: "广州",
},
};
},
});
// 挂载
app.mount("#app");
</script>
</body>
</html>
3.2 列表数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../lib/vue.js"></script>
<script>
// 创建app
const app = Vue.createApp({
template: `
<h1>{{msg}}</h1>
<h2>电影列表</h2>
// v-for 可以遍历数据/对象,对应的item就是数组的每一项
// 如果将来这个电影数组中有 100 1000 10000部电影
// 我的代码不用动
<ul>
<li v-for="item in movies">{{item}}</li>
</ul>
`,
data:function() {
return {
msg: "广州笑笑",
movies:["孤注一掷","巨齿鲨2","热烈","封神","消失的她","八角笼中","芭比","长安三万里"]
};
},
});
// 挂载
app.mount("#app");
</script>
</body>
</html>
3.3 计数器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../lib/vue.js"></script>
<script>
// 创建app
const app = Vue.createApp({
// 需要绑定事件,点击事件
// @+事件名 = 事件处理函数
template: `
<h1>{{counter}}</h1>
<button @click="add">+</button>
<button @click="sub">-</button>
`,
data:function() {
return {
counter:0,
};
},
// 所有的方法也需要交给vue,不然模版里面是访问不到的
methods:{
add(){
this.counter++;
},
sub(){
this.counter--;
}
}
});
// 挂载
app.mount("#app");
</script>
</body>
</html>
重构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{counter}}</h1>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<script src="../lib/vue.js"></script>
<script>
// 创建app
const app = Vue.createApp({
// 需要绑定事件,点击事件
// @+事件名 = 事件处理函数
// template: `
// <h1>{{counter}}</h1>
// <button @click="add">+</button>
// <button @click="sub">-</button>
// `,
// tempalte的优先级更高
// template:"<h1>这里是template的内容</h1>",
data: function () {
return {
counter: 0,
};
},
// 所有的方法也需要交给vue,不然模版里面是访问不到的
methods: {
add() {
this.counter++;
},
sub() {
this.counter--;
},
},
});
// 挂载
app.mount("#app");
</script>
</body>
</html>
4.声明式和命令式编程
原生开发和Vue开发模式的不同,因为这是两种完全不同的编程模式
命令式编程(原生)
命令式编程需要用代码来明确的指出每一步该怎么做
how to do(怎么做)
声明式编程(vue):
也是一种编程范式,与命令式编程相对立
它描述目标的性质,让计算机明白目标,而非流程
what to do(做什么),由框架完成how的过程
5.MVVM和MVC
都是软件的架构体系
MVC:Model、view、Controller的简写,在前期被广泛使用,比如后端,IOS,前端
MVVM:Model、view、viewModel,是目前非常流行的架构
model:数据
view:界面
view model:对应在vue中就是vue,也就是帮我们自动管理视图和数据的关系
6.options-data属性选项
data属性是一个函数,并且这个函数需要返回一个对象
在Vue2.x版本,可以直接写一个对象(官方推荐是一个函数)
在Vue3.x版本,必须是一个函数,否则直接报错
data返回的对象会被Vue的响应式系统进行劫持(监听属性值的访问和修改),之后对该对象的属性的修改和访问都会在劫持中被处理
6.1 为什么data必须是一个函数
这并非是Vue自身要这么设计,而是跟javascript特性相关
在vue中每一个组件(SFC文件),都是Vue的一个实例
JS中实例是通过构造函数来创建的,每个构造函数可以new出很多个实例,那么每个实例都会继承原型上的方法或属性。
vue的data数据其实是Vue原型上的属性,数据存在于内存当中。vue为了保证每个实例上的data数据的独立性,规定了必须使用函数,而不是对象。
因为使用对象的话,每个实例(组件)上使用的data数据是相互影响的。对象是对于内存地址的引用,直接定义一个对象的话,组件之间都会使用这个对象,这样就会造成组件之间数据相互影响
7.options-methods属性选项
在methods中不能使用箭头函数,理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例
不使用箭头函数的情况下,this到底指向是谁?
它内部定义了一个publicThis的变量保存代理的实例,然后读取选项api中的methods,遍历所有函数,通过Object.defineProperty给每个函数用bind绑定了publicThis,这样每个methods中的函数访问this拿到的就是代理的实例,拿到data中的数据
1.不能写箭头函数
2.vue已经帮我们绑定好this方便我们操作数据
8.代码片段
日常开发,学习有一些代码块,我们是许哟啊经常使用,我们可以利用vscode的代码片段,而不需要每次手动书写,如何配置代码片段
1.复制自己需要的代码片段
2.在网站中生成对应的代码片段:https://snippet-generator.app/
3.在vscode中配置
9.Mustache语法
React的开发模式
react是使用jsx,所有的代码都是一种类似js的方式,之后通过babel将jsx编译成React.createElement来使用
Vue的开发模式:
使用基于html的模版语法,在模版中允许开发者以声明式的方法将DOM和底层组件实例的数据绑定在一起
如果我们希望在vue中展示数据,使用最多的语法就是mustache语法(双大括号)的文本插值,也有人叫他双胡子语法。之前写的都是data中的数据,实际上它里面还可以是一个js表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 基本使用 -->
<h1>{{msg}}</h1>
<!-- 表达式 -->
<h2>{{counter * 3}}</h2>
<h2>{{info.split(" ")}}</h2>
<!-- 三元表达式 -->
<h2>{{age>=18?"成年":"未成年"}}</h2>
<!-- 调用methods中的方法 -->
<h2>{{formateDate()}}</h2>
<!-- !!!!!不要写定义语句 -->
<!-- <h2>{{let name = "ZD"}}</h2> -->
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
msg: "成年",
counter: 100,
info: "my name is ZD",
age: 20,
};
},
methods: {
formateDate() {
return "2023-08-15";
},
},
});
app.mount("#app");
</script>
</body>
</html>
10. 常见的基本指令
10.1 v-once指令
用于指定的元素或者组件只渲染一次
当数据发生变化的时候,元素/组件以及其子元素都视为静态内容并且跳过编译,该指令可用于性能优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 如果是子节点也只会渲染一次 -->
<div v-once>
<!-- 只渲染一次,哪怕后续数据有变化我也不在更新 -->
<h1>{{counter}}</h1>
<p>{{info}}</p>
</div>
<button @click="updata">+1</button>
<button @click="changeInfo">修改笑笑信息</button>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
counter:0,
info:"天河笑笑--alex"
}
},
methods: {
updata(){
this.counter++;
console.log(this.counter);
},
changeInfo(){
this.info = "广东笑笑"
}
}
});
app.mount("#app");
</script>
</body>
</html>
10.2 v-text 指令
用于更新元素的textContent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2>abcd{{msg}}efg
</h2>
<!-- msg的内容会覆盖掉原有的内容 -->
<h2 v-text="msg">
</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
msg:"白云"
}
},
methods: {
}
});
app.mount("#app");
</script>
</body>
</html>
10.3 v-html 指令
解析html字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2>aaaa{{msg}}</h2>
<h2 v-text="msg">aaaa</h2>
<h2 v-html="msg">aaaa</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
msg:`
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
`
}
},
methods: {
}
});
app.mount("#app");
</script>
</body>
</html>
10.4 v-pre
v-pre用于跳过元素和他的子元素的编译过程,显示原始的mustache标签,用户跳过不需要编译的节点,加快速度。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<div v-pre>
<h2 v-pre>{{msg}}</h2>
<h2 v-pre>{{msg}}</h2>
<h2 v-pre>{{msg}}</h2>
</div>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
msg:"湛江生蚝"
}
},
methods: {
}
});
app.mount("#app");
</script>
</body>
</html>
10.5 v-cloak
这个指令保持在元素上,直到关联组件实例结束编译。往往会和css一起使用,防止用户看到{{}}结构。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<h2 v-cloak>{{msg}}</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
msg: "白云白云",
};
},
methods: {},
});
app.mount("#app");
</script>
</body>
</html>
10.6 v-memo
部分缓存
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-memo memory 记忆 -->
<!-- 只有name的更新才会导致重新渲染其他的age、title的更新, age、title的更新不会重新渲染甚至Vnode VDOM都不会创建-->
<div v-memo="[name]">
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<h2>{{title}}</h2>
</div>
<button @click="changeAge">改变age</button>
<button @click="changeName">改变name</button>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
name:"alex",
age:88,
title:"天河笑笑"
}
},
methods: {
changeName(){
this.name = "jack"
console.log(this.name,this.age);
},
changeAge(){
this.age++;
this.title="广东笑笑"
console.log(this.name,this.age);
}
}
});
app.mount("#app");
</script>
</body>
</html>
11.v-bind绑定属性(重点掌握)
前面讲的一系列的指令,主要是将值插入到模板中,或者向另一个组件传递值
在开发中,有一些属性需要动态绑定,比如:a的href、图片的src、动态的绑定一些class/style等等。
v-bind
缩写 :就是一个冒号 --------- `:`
用法 动态地绑定一个或者多个attribute,或者给组件prop传值
11.1 绑定基本属性
两个注意事项:
1.不要忘记加冒号
2.在methods中操作data中的数据时,记得加this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
img{
width: 300px;
display: block;
}
</style>
</head>
<body>
<div id="app">
<!-- 把imgUrl1当作资源名称,而不是data中的一个变量来解析 -->
<!-- <img src="imgUrl1" alt=""> -->
<!-- 缩写 -->
<!-- 把imgURl1当作变量解析变量的值 -->
<!-- <img :src="imgUrl1" alt=""> -->
<!-- <a :href="href">百度一下</a> -->
<!-- 根据条件来渲染 -->
<!-- <img :src="switchImg()" alt=""> -->
<!-- 切换图片 -->
<img :src="defaultUrl" alt="">
<button @click="switchImg">切换图片</button>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
defaultUrl:"",
imgUrl1:"https://t7.baidu.com/it/u=1415984692,3889465312&fm=193&f=GIF",
imgUrl2:"https://t7.baidu.com/it/u=334080491,3307726294&fm=193&f=GIF",
href:"https://www.baidu.com"
}
},
methods: {
switchImg(){
this.defaultUrl = this.defaultUrl == this.imgUrl1 ? this.imgUrl2 : this.imgUrl1
// return this.defaultUrl;
}
}
});
app.mount("#app");
</script>
</body>
</html>
11.2 绑定class
数据为某个状态的时候,字体为红色,数据时另一个状态的时候我们的字体为黑色。
绑定class有两种方法
1.对象语法
2.数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.active{
color: red;
}
.yh{
background-color: aqua;
}
</style>
</head>
<body>
<div id="app">
<!-- 基本的绑定 -->
<!-- <h2 :class="classes">hello world</h2>
<h2 :class="isActive ? 'active' : '' ">严浩 唱 跳 rap 篮球</h2>
<button @click="changeYH">改变YH的颜色</button> -->
<!-- 动态class可以写对象语法 -->
<!-- 对象的基本语法 -->
<!-- active类名是否生效根据isActive的布尔值来决定 -->
<!-- <h2 :class="{active:isActive}">严浩 唱 跳 rap 篮球</h2> -->
<!-- 对象语法的多个键值对 -->
<!-- <h2 :class="{active:isActive,yh:true,abc:true,acd:false}">严浩 唱 跳 rap 篮球</h2> -->
<!-- 动态的class和普通的calss可以同时使用 -->
<!-- <h2 class="yh" :class="{active:isActive}">严浩 唱 跳 rap 篮球</h2> -->
<!-- methods -->
<!-- <h2 :class="classList()">严浩 唱 跳 rap 篮球</h2> -->
<!-- 数组语法 -->
<h2 :class="['active','yh','abc','acd']">笑笑 唱 跳 rap 篮球</h2>
<h2 :class="['active',isActive ? 'yh' : '']">笑笑 唱 跳 rap 篮球</h2>
<h2 :class="['active',{yh:isActive}]">笑笑 唱 跳 rap 篮球</h2>
<h2 :class="classL">笑笑 唱 跳 rap 篮球</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
classes:"active aaa bbb ccc balabala",
isActive:false,
classL:['active','xx']
}
},
methods: {
changeYH(){
this.isActive = !this.isActive;
},
classList(){
return {active:this.isActive,yh:true,jack:false};
}
}
});
app.mount("#app");
</script>
</body>
</html>
11.3 绑定style
书写css property属性时,可以用驼峰式也可以用短横线分隔,但是在动态绑定样式时只能用驼峰形式
绑定style也是两种方式
1.对象
2.数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 普通的行内样式语法 -->
<h2 style="color: red; font-size: 30px">111111</h2>
<!-- style中某些值来自于data 就要用: -->
<!-- 在模版动态绑定的时候不能用短横线命名只能用驼峰 -->
<h2 :style="{color:fontColor,fontSize:fontSize}">2222222</h2>
<!-- 动态绑定style,属性是一个对象 -->
<h2 :style="objStyle">333333</h2>
<!-- style数组语法 -->
<h2 :style="[objStyle,{backgroundColor:'pink'}]">4444444</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
fontColor:"blue",
fontSize:"60px",
objStyle:{
fontSize:"100px",
color:"green"
}
};
},
methods: {},
});
app.mount("#app");
</script>
</body>
</html>
11.4 动态绑定属性
a标签的href、img的src、class、style属性名都是固定的,如果属性不固定,我们可以使用:[属性]=“属性值”,这种绑定的方式我们称为动态绑定属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2 :[name]="'aaaa'">1231</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
name:"data-id",
aaaa:"abcd"
}
},
methods: {
}
});
app.mount("#app");
</script>
</body>
</html>
11.5 v-bind直接绑定一个对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 如果我给某个组件prop下去的属性值特别多 -->
<!-- 以对象的形式传递 -->
<!-- 给组件传递参数 -->
<h1 :info="infos">alex3333</h1>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
infos:{
name:"alex",
height:1.88,
age:18
}
}
},
methods: {
}
});
app.mount("#app");
</script>
</body>
</html>