一、Vue快速上手
1.Vue概念
Vue是一个用于构建用户界面的渐进式框架
- 构建用户界面
基于数据,渲染出用户看到的页面- 渐进式
循序渐进- Vue的两种使用方式:
①Vue核心包开发
场景:局部模块改造
②Vue核心包&Vue插件工程化开发
场景:整站开发- 框架
开发一个中大型的项目
1.1.Vue优点和缺点
1.1.1优点
大大提升开发效率
1.1.2缺点
需要理解记忆规则(官网)
2.创建实例
2.1准备容器
2.2引入核心包
- 开发版本
- 生产版本
2.3创建Vue实例 new Vue()
2.4填充配置项
使用的是哪些数据,渲染的是哪个容器
- el指定挂载点
跟一个选择题,判断是渲染哪一个容器- data 提供数据
渲染页面
2.5创建Vue实例演示代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-创建Vue实例</title>
</head>
<body>
<!-- 创建Vue实例:初始化渲染
第一步:准备容器 (Vue所管理的范围)
第二步:引入核心包(开发版本/生产版本) 官网
第三步:创建实例
第四步:添加配置项=>完成渲染
-->
<div id="sparkle">
<!-- 编写一些用于渲染的代码逻辑 -->
<h1>{{ msg }}</h1>
<a href="#"> {{ count }}</a>
</div>
<p>---------------------------------------------------</p>
<div class="app">{{ msg }}</div>
<!-- 引入的是开发版本的包 包含完整的注释和警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 一旦引入VueJS核心包,在全局环境,就有了Vue构造函数
const sparkle = new Vue({
// 通过el配置选择器,指定Vue管理的是哪个盒子
el: "#sparkle",
// 通过data提供渲染的数据
data: {
msg: "你好,Vue,amazing",
count: 666,
},
});
</script>
</body>
</html>
3.插值表达式
3.1概念
3.1.2定义
- 语法:
{{ 表达式 }}
- 定义:插值表达式是一种Vue的模版语法
3.2作用
利用表达式进行插值,渲染到页面中
表达式
是可以被求值的代码,JS引擎会将其计算出一个结果
但凡是表达式,就可以放入双括号
<h3>{{ title }}</h3>
<p>{{ nickname.toUpperCase() }}</p>
<p>{{age >=18 ? '成年' : '未成年' }}</p>
<p>{{ obj.name }}</p>
3.3注意点
- 使用的数据必须存在(data)
- 内容仅支持表达式,并非是语句(if,for)
- 不能在标签属性中使用
{{}}
插值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>02-插值表达式</title>
</head>
<body>
<div id="sparkle">
{{ username }}
<hr />
{{ username.toUpperCase() }}
<hr />
{{ username + 'nice to meet you!' }}
<hr />
{{ password }}
<hr />
{{ age >= 18 ? '成年' : '未成年'}}
<hr />
<!-- 先找到friend这个变量,然后访问变量里面的值,点语法 -->
<!-- 从一级开始往下访问 -->
{{ friend.friendName + friend.hobby }}
<hr />
<!-- {{ hhh }} -->
<!-- 注意点1:使用的数据要存在 -->
<!-- 会报错!!! -->
<hr />
<!-- {{ if }} -->
<!-- 注意点2:{{ }}中支持的是表达式,而不是语句 -->
<!-- 禁止在模版插值中使用JS的关键字 -->
<hr />
<!-- 注意点3:不能在标签属性中使用{{ }}插值 -->
<!-- 会编译错误 -->
<p title="{{ username }}">你好</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const sparkle = new Vue({
// 管理哪个容器
el: "#sparkle",
// 提供数据
data: {
username: "Mike",
password: "128229",
age: 20,
friend: {
friendName: "Tom",
hobby: "热爱学习 Vue",
},
},
});
</script>
</body>
</html>
4.Vue核心特性:响应式
- 当数据发生变化时,相关的视图会自动更新
数据的响应式处理 => 响应式:数据变化,试图自动更新
- 访问data中的数据
"实例.属性名"
- 修改data中的数据
"实例.属性名"=" 值 "
- 聚焦于数据 => 数据驱动视图
- 使用Vue开发 => 专注于业务核心逻辑即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>03-响应式</title>
</head>
<body>
<div id="sparkle">{{ msg }}</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const sparkle = new Vue({
el: "#sparkle",
data: {
// 响应式数据
username: "LiHua",
class: 2,
hobby: "sleep",
msg: "你好",
},
});
// data中的数据会加在实例上的
// 1.访问数据 实例.属性名
// 2.修改数据 实例.属性名 = 新值
</script>
</body>
</html>
5.开发者工具
- 极简插件
第一步
点击即可跳转至极简插件的官网
第二步
右上方搜索框输入"Vue",点击第一个
第三步
点击推荐下载,记得解压
第四步
在edge浏览器的右上角找到这个图案,点击之后,再点击管理扩展
第五步
在左下方,点击开启开发人员模式
第六步
将刚刚解压完成的crx为后缀的文件拖入最后一张图片的页面即可
第七步
打开Vue运行的页面,调试工具Vue栏,即可查看/修改数据,进行调试
二、Vue指令
- Vue会根据不同的指令,针对标签实现不同的功能
- 指令:带有v-前缀 的特殊标签属性
1. v-html
- 语法
v-html="表达式"
- 功能
动态设置元素innerHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>05-指令体验</title>
</head>
<body>
<!-- 插值表达式并没有正确地解析标签,而是以纯文本的形式展现在文本中 => 插值表达式不具备解析标签的能力 -->
<div id="blue" v-html="msg"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const blue = new Vue({
el: "#blue",
data: {
msg: `<a href="http://baidu.com.cn">百度</a>
<br>
<h3>今天很blue</h3>
`,
},
});
</script>
</body>
</html>
2. v-show和v-if
2.1 v-show
- 语法
v-show="表达式"
表达式的值是true显示,是false隐藏
- 功能
控制元素显示/隐藏 - 原理
本质上是在切换CSS中的display:none
来控制元素的显示与隐藏 - 使用场景
频繁切换显示/隐藏的场景
2.2 v-if
- 语法
v-if="表达式"
表达式的值是true显示,是false隐藏
- 功能
控制元素显示/隐藏(条件渲染) - 原理
本质上是在根据判断条件控制元素的创建 和移除(条件渲染) - 使用场景
不频繁切换要么显示,要么隐藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>06-v-show和v-if指令</title>
<style>
#container {
width: 250px;
height: 300px;
background-color: paleturquoise;
}
.box {
width: 200px;
height: 120px;
line-height: 120px;
text-align: center;
border: 3px solid rgb(5, 31, 68);
border-radius: 5px;
margin-top: 15px;
margin-left: 25px;
}
</style>
</head>
<body>
<div id="container">
<div class="box" v-show="flag">你好,我是v-show</div>
<!-- 本质上是在切换CSS中的 display:none 来控制元素的显示与隐藏 -->
<div class="box" v-if="flag">你好,我是v-if</div>
<!-- 本质上是在根据判断 条件控制 元素的 创建 和 移除 (条件渲染)-->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const container = new Vue({
el: "#container",
data: {
flag: true,
},
});
</script>
</boy>
</html>
3. v-else和v-else-if
3.1v-else
- 语法
v-else
后面不需要跟任何内容 - 功能
辅助v-if
进行判断渲染 - 注意点
需要紧挨着v-if
一起使用,不能单独使用
3.2v-else-if
- 语法
v-else-if="表达式"
- 功能
辅助v-if
进行判断渲染 - 注意点
需要紧挨着v-if
一起使用,不能单独使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>07-v-else和v-else-if指令</title>
</head>
<body>
<div id="container">
<p v-if="gender === 1">性别:♀男生</p>
<p v-else>性别:♂女生</p>
<!-- v-else不能单独使用,需要配合着v-if一起使用 -->
<hr />
<p v-if="grade >= 90">成绩评定A:奖励电脑一台</p>
<p v-else-if="grade >= 70">成绩评定B:奖励科技馆一日游</p>
<p v-else-if="grade >= 60">成绩评定C:奖励零食大礼包</p>
<p v-else>成绩评定D:惩罚上交一周手机</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const container = new Vue({
el: "#container",
data: {
gender: 2,
grade: 95,
},
});
</script>
</body>
</html>
4. v-on
- 语法:
- 语法1
v-on:事件名="内联语句"
内联语句:可执行的代码
使用范围:适用于简单的逻辑
- 语法2
v-on:事件名="methods中的函数名"
methods是类似于data的一个存在,用来提供处理逻辑函数
- 功能:
注册事件= 添加监听 + 提供处理逻辑 - 简写:
将v-on:代替成@
<button v-on:click="count--">-</button>
<button @click="count--">-</button>
- 注意点:
- methods中的this就指向创建的Vue实例
- methods中不能直接使用data中的数据,而是需要通过创建的实例进行访问
5. v-on调用传参
<button @click="fn(参数1,参数2)">按钮</button>
const sparkle = new Vue({
el: "#sparkle",
methods: {
fn(a, b) {
console.log("首先这是一个fn函数,其次是可以传递参数的,a和b是形参");
},
},
});
6. v-bind
- 语法:
v-bind:属性名="表达式"
- 功能:
动态地设置html的标签属性(src、url、title) - 简写:
:属性名="表达式"
7. v-for
- 遍历数组语法:
v-for="(item,index) in 数组名"
item是指遍历时的每一项
index是遍历时每一项的下标
- 功能:
基于数据 循环,多次 渲染整个元素
(可以遍历数组、对象、数字) - 注意点:
语法中的index如果在后续用不到,可以省略,写成v-for="item in 数组名"
8. v-for中的 key (重要!!!)
- 语法:
key属性 = "唯一标识"
<li v-for="(item,index) in booksList" :key="item.id">
- 作用:
给列表项添加的唯一标识,便于Vue进行列表项的正确排序复用
v-for的默认行为会尝试原地修改元素(就地复用)
- 注意点:
- key的值只能是字符串 或数字类型
- key的值必须具有weiyix
- 推荐使用id 作为key(唯一),不推荐使用index作为key(会变化,不对应)
9. v-model
- 语法:
v-model="变量"
- 功能:
给 表单元素 使用,双向数据绑定 => 可以快速 获取 或 设置 表单元素内容
数据变化 => 视图自动更新
视图变化 => 数据自动更新
三、综合案例-saprkle记事本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>sparkle记事本</title>
<style>
* {
margin: 0;
padding: 0;
}
#sparkle {
width: 500px;
margin: 50px auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.title {
font-size: 48px;
font-weight: 200;
width: 450px;
height: 70px;
line-height: 70px;
text-align: center;
color: rgb(7, 43, 71);
}
.contentBox {
width: 450px;
/* height: 200px; */
background-color: rgb(214, 235, 247);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.addContent {
width: 420px;
height: 70px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
}
.addContent .input {
width: 300px;
height: 50px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border: 1px solid rgb(12, 76, 125);
}
.addContent .input input {
border: none;
width: 300px;
height: 50px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
font-size: 18px;
}
.addContent .input input:focus {
outline: none;
}
.addContent .add {
width: 120px;
height: 51.5px;
line-height: 50px;
background-color: rgb(12, 76, 125);
text-align: center;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.addContent .add .add-task {
border: none;
cursor: pointer;
color: white;
background-color: rgb(12, 76, 125);
font-size: 20px;
font-weight: 300;
}
.content {
width: 420px;
height: 40px;
border-bottom: 1px solid gray;
display: flex;
justify-content: flex-start;
}
.content:hover .del {
display: block;
}
.content .textContent {
width: 330px;
height: 40px;
line-height: 40px;
}
.content .del {
width: 70px;
height: 40px;
line-height: 40px;
text-align: center;
display: none;
}
.content .del .destroy {
border: none;
font-size: 15px;
color: gray;
background-color: rgb(214, 235, 247);
cursor: pointer;
}
.function {
width: 420px;
height: 20px;
display: flex;
justify-content: space-between;
color: gray;
}
.function .clear-completed {
border: none;
color: rgb(12, 76, 125);
background-color: transparent;
cursor: pointer;
}
</style>
</head>
<body>
<div id="sparkle">
<div class="title">sparkle记事本</div>
<div class="contentBox">
<div class="addContent">
<div class="input">
<input
type="text"
value=""
placeholder="请输入任务"
v-model="todoName"
/>
</div>
<div class="add">
<button @click="addTask" class="add-task">添加任务</button>
</div>
</div>
<div class="content" v-for="(item,index) in task " :key="item.id">
<!-- @mouseenter="controlShow"
@mouseleave="controlShow" -->
<div class="textContent">
<!-- 这里用id的话,若删除某一个任务,序号便会不连贯 -->
<span class="index">{{ index + 1 }}.</span>
<span> {{ item.name }} </span>
</div>
<div class="del">
<!-- 此处一定要使用id -->
<button class="destroy" @click="del(item.id)">✖</button>
</div>
</div>
<!-- 如果没有任务,下方的合计和清空任务需要隐藏 -->
<div class="function" v-show="task.length > 0">
<div class="sum">合计:<strong>{{ task.length }}</strong></div>
<div class="clear">
<button @click="clear" class="clear-completed">清空任务</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 添加功能
// 1.获取输入框的内容v-model
// 2.点击按钮,新增任务 => 往数组中加元素
const sparkle = new Vue({
el: "#sparkle",
data: {
todoName: "",
task: [
{ id: 1, name: "学习Vue" },
{ id: 2, name: "跑步20min" },
{ id: 3, name: "睡觉" },
],
},
methods: {
del(id) {
this.task = this.task.filter((item) => item.id !== id);
// console.log(id);
},
addTask() {
//trim() 会移除字符串两端的空白字符,而不会移除字符串内部的空格
// 加一个判断,使得任务名称不能为空
if (this.todoName.trim() === "") {
alert("任务名称不能为空!");
return;
}
this.task.push({
// 使用时间戳当做id,来保持唯一性
id: +new Date(),
name: this.todoName,
});
// 在点击"添加任务之后",输入框的内容需要清除
this.todoName = "";
},
clear() {
this.task = [];
},
},
});
</script>
</body>
</html>