一.vue概述于环境搭建
1.1Vue概述
1.1.1简介
Vue 是一款轻量级的用于构建用户界面的 渐进式的JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
Vue 还可以与其他库或框架结合使用,例如 React 或 AngularJS。它还可以与现代工具链和构建工具进行集成,例如 Webpack 或 Gulp,使其更加灵活和可扩展。
Vue的发明人:尤雨溪
Vue2官网:https://v2.cn.vuejs.org/
Vue3官网:https://cn.vuejs.org/guide/introduction
1.1.2渐进式
所谓渐进式,你可以理解为:就是一开始不需要你完全掌握它的全部功能特性,可以后续逐步增加功能。不多做职责之外的事情
VUE不强求你一次性接受并使用它的全部功能特性,它允许开发者按照自己的需求逐步地引入Vue的功能和特性。
-
例如,你可以只使用Vue的数据绑定和模板语法,而不使用Vue的路由和状态管理。
再比如,你现在有一个传统的多页面 Web 应用程序,其中有一个页面是一个简单的待办事项列表,你希望在这个页面中引入 Vue.js 来提供更好的交互性和用户体验。
-
这个时候,你只需要引入Vue.js核心库,然后使用Vue来管理列表的状态即可。 客户无感,并且很平滑的过渡。
-
一个月后,你引入vue-router 来实现路由导航。
-
两个月后,引入Vuex 来管理待办事项列表的状态,并使用单文件组件来组织代码等。
通过逐步引入 Vue.js 的各种功能,你可以在不中断现有功能的情况下,改进现有的 Web 应用程序,使其具备更好的交互性和用户体验。这种渐进式的特性使得 Vue.js 成为一个非常灵活和可扩展的前端框架。
传统的前端框架通常会将整个项目的架构和开发方式紧密地绑定在一起,开发者必须按照预先确定的框架结构和规则来进行开发。这种方式在一些大型项目中可能会产生一些问题,比如过于复杂的架构、开发效率低下、难以进行增量开发等。
1.1.3Vue的核心思想
vue在框架的设计上,采用了两个核心思想,一个是响应式数据绑定(也叫数据驱动),另一个就是组件化。
在vue中,数据的改变会驱动视图的自动更新。传统的做法是需要手动改变DOM来使得视图更新,而vue只需要改变数据。
这是通过使用ES5的`Object.defineProperty()`实现数据的观察,或者ES6的`Proxy`实现的。
let name = "michael"
document.getElementById("input").value = name;
name="lucy" <==改变了数据(状态)
document.getElementById("input").value = name; <==还得操作一次DOM对象
组件化
可以将页面拆分为不同的组件,每个组件都包含自己的HTML模板、JavaScript代码和CSS样式。一是提高代码的复用性,二能降低数据之间的耦合度。组件之间也可以进行通信。 一个页面/模块可以由多个组件所组成
1.1.4 框架与库的区别(扩展知识)
所谓框架:就是一套完整的解决方案,实现了大部分功能,我们只需要按照一定的规则去编码即可。如果把一个完整的项目比喻为一个装修好的房子,那么框架就是一个毛坯房。我们只需要在“毛坯房”的基础上,增加功能代码即可。
库:类似工具箱,是一堆方法的集合,比如 axios、lodash、echarts等
下图是 库 和 框架的对比。
框架的特点:有一套必须让开发者遵守的规则或者约束
1.2环境搭建
1.2.1引入js
1.网络环境
<!-- 引用网络上的vue.js 开发版本-->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> -->
<!-- 引用网络上的vue.min.js 生产版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
2.本地环境(离线引入)
生产版本
<!-- 使用本地文件的生产版本, 该版本没有警告和调试功能 -->
<script src="./js/vue.min.js"></script>
开发版本
<!-- vue.js的引用: 使用本地文件,开发版本,带有警告和调试功能 -->
<script src="./js/vue.js"></script>
1.2.2开发者工具
1. 通过谷歌应用商店安装(国外网站)
2. 极简插件下载(推荐) https://chrome.zzzmh.cn/index
3. github上下载:https://github.com/vuejs/vue-devtools.git
(1)离线安装
下载crx插件,按照下图步骤安装即可
1.3设置默认浏览器
第一步:查看您的默认浏览器是什么
方式1: windows系统的搜索《默认应用》,查看里面的web浏览器 方式2: 创建一个扩展名为html的文件,图标是哪个浏览器,即默认浏览器
第二步:修改google浏览器为默认浏览器
方式1: 打开google浏览器, 有提示,按照提示来,即可。 方式2: windows系统搜索《默认应用》,查看里面的web浏览器,设置web浏览器
第三步: 设置浏览器的启动页为你喜欢的网页
google浏览器的设置--->启动时----->打开特定网页或一组网页--->添加新网页---www.baidu.com-->点击添加
1.4入门案例演示
1.4.1核心步骤
1.引入js文件
2.准备容器
3.创建Vue实例
4.指定配置型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue的入门案例</title>
<!-- 第一步: 引入vue文件 -->
<script type="text/javascript" src="../myjs/vue.js"></script>
</head>
<body>
<div id="app">
<h1>你好,{{subject}},我是{{name}}</h1>
</div>
</body>
<!--
el的两种写法:
-1. 在创建Vue实例中,指定该配置项: el: 'css选择器'
-2. 调用Vue实例的挂载方法进行挂载: vm.$mount('css选择器')
data的两种写法:
-1. 对象写法: data:{}
-2. 函数写法: 组件开发时,必须使用函数写法,并且不能使用箭头函数形式,否则报错
data:function(){
return {
...
}
}
-->
<script>
new Vue({
// el: "#app", //指定属性el
// data: { //对象写法
// subject: "java",
// name: "michael"
// }
data() { // 函数写法
return { "subject": "vue", "name": "michael" }
}
}).$mount('#app') // 调用方法
</script>
</html>
1.4.2注意事项
1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
3. root容器里的代码被称为Vue模板
4. Vue实例与容器是一一对应的
5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用
6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
7. 一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新
1.4.3解决f12里的警告
正常情况下:只需要在Vue实例之前配置如下设置,即可
<script type="text/javascript">
// 修改配置项的productionTip为false,可以解决f12的第二个警告
Vue.config.productionTip = false;
const vm = new Vue({
// ......
})
</script>
但是:该配置,对最新版本的chrome浏览器无效,因为浏览器默认直接回调遇到的第一个script。 而引用的vue.js是第一个,里面的值为true。因此手动设置的false,不生效。 那么如何解决不生效的问题
第一种方式. 如上配置,然后将vue.js里的延迟时间调大。 参考下图
第二种方式. 直接修改vue.js里的productionTip的值为false,可以搜索这个值
1.5MVVM模型
在Vue框架中,MVVM是指“模型-视图-视图模型”,是一种用于构建用户界面的架构模式。MVVM将用户界面分为三个主要部分:
-
模型(Model):表示应用程序中的数据和业务逻辑。
-
视图(View):表示用户界面,即用户可以看到和与之交互的部分。通常是由HTML和CSS组成。
-
视图模型(ViewModel):连接模型和视图,充当桥梁。
在Vue中,模型通常是由组件的状态(state)和方法(methods)来表示的。
-
状态是组件的数据,可以是原始数据类型、对象或数组,这些状态可以通过Vue实例的数据对象来管理。
-
方法是组件中定义的行为,用于实现模型中的业务逻辑。
在Vue中,视图可以通过模板(template)来描述,模板可以包含指令和表达式,用于实现视图的动态渲染和事件处理。
-
指令是一种特殊的HTML属性,用于描述视图和模型之间的绑定关系。
-
表达式是一段JavaScript代码,用于计算视图中的值。
视图模型是Vue中最重要的概念之一,它是连接模型和视图的桥梁。在Vue中,视图模型是由Vue实例来扮演的,Vue实例通过响应式的数据绑定,将视图和模型进行连接。当视图中的状态发生变化时,Vue实例会自动更新模型中的数据,反之亦然。视图模型还负责处理用户与视图之间的交互,例如监听用户输入、处理点击事件等。视图模型可以使用Vue提供的指令和生命周期钩子函数来实现这些功能。
这种架构模式的==好处在于它可以将代码分离成不同的层次,使得开发更容易维护和扩展。视图和模型之间的通信是通过视图模型来实现的,这消除了视图和模型之间的直接耦合,使得应用程序更加灵活和可测试。
MVVM的优点:
1. 数据绑定:
Vue实现了响应式的数据绑定,将视图和数据状态进行绑定,当数据状态发生变化时,视图会自动更新。这样,开发人员可以更容易地管理和更新视图状态,而无需手动操作DOM元素。
2. 模板系统:
Vue提供了一种基于HTML的模板系统,使开发人员可以轻松地创建动态、可重用的UI组件。这种模板系统使得编写复杂的UI界面变得更加简单和直观。
3.事件处理:
Vue提供了一个基于指令的事件处理系统,使开发人员可以通过声明式语法绑定事件处理程序。这种方式让事件处理更加简单和清晰。
总之,在Vue中,MVVM架构提供了一种灵活、可维护的方式来组织应用程序的代码。开发人员可以将代码分离成不同的层次,每个层次都有自己的职责和功能。Vue的MVVM架构还提供了强大的数据绑定、模板系统和事件处理功能,使开发人员可以更加轻松地构建高质量的用户界面。
二模版语法与生命周期
2.1模版与模版语法简介
2.1.1什么是模版
模版语法指的就是可以在模版中书写的格式语法。 分两类写法,分别是插值语法和指令语法
插值语法:
写法:{{xxx}} xxx是js表达式,且可以直接读取到data中的响应数据
功能:用于解析标签体内容 比如: <div> 标签体 </div> {{schoolName}}
插值语法应用场景:简单的获取data里的数据,并不适合参与复杂的运算
指令语法:
写法: v-??? 比如 v-bind、v-model、v-cloak、v-for、v-if、v-show等
功能: 用于解析标签, 包括标签属性,标签体内容,绑定事件等
指令是 Vue 提供的带有 v- 前缀 的特殊标签属性。 可以提高程序员操作 DOM 的效率。
vue 中的指令按照不同的用途可以分为如下 6 大类:
-
属性绑定指令 (v-bind)
-
双向绑定指令(v-model)
-
事件绑定指令(v-on) @
-
内容渲染指令(v-html、v-text)
-
条件渲染指令(v-show、v-if、v-else、v-else-if)
-
列表渲染指令(v-for)
指令是 vue 开发中最基础、最常用、最简单的知识点。
2.2插值语法
<!-- 第一步:引入js文件 -->
<script src="./js/vue.js"></script>
<!-- 第二步:准备容器 -->
<div id="demo">
<!--
1. 插值语法的格式:{{表达式}}
2. 什么是表达式: 可以返回一个值的式子
举例说明: i 1+1 a+b new Date() Date.now()
a>b?"你真帅":"你真漂亮"
arr[1]
person.name
-->
<h1>我叫{{name}},我的爱好是{{hobbys}}</h1>
<h1>我的同伴是{{lover.name}},年龄是{{lover.age}}</h1>
</div>
<script>
// 第三步:创建Vue实例对象
const vm = new Vue({
// 第四步: 配置数据。
el:"#demo",
data:{
name:"佩奇",
hobbys:["book","movie","basketball"],
lover:{name:"只因哥",age:21}
}
})
</script>
2.3指令语法
2.3.1属性绑定指令
Vue中有2种数据绑定的方式:
-
单向绑定(v-bind): 数据只能从data流向页面
-
简便写法:
:属性="表达式"
-
-
双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
-
该指令只能作用于表单带有value属性的元素上。比如:文本框,密码框,单选框,复选框,多行文本域
-
简便写法:
v-model="表达式"
-
<script src="../js/vue.js"></script>
<body>
<div id="root">
单向数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model:value="name"><br>
证明是表达式:<br>
<a v-bind:href="url.toUpperCase()">点我去百度搜索页面</a><br>
简化写法:<br>
<input type="text" :value="name"><br>
<input type="text" v-model="name"><br>
<!-- h3不是表单内部的元素,没有value属性,不可以用v-model -->
<!-- <h3 v-model:name="name">百度</h3> -->
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'michael',
url:"www.baidu.com"
}
})
</script>
</body>
2.3.2事件绑定指令
<script type="text/javascript" src="../js/vue.js"></script>
<!--
事件的基本应用:
-1. 使用v-on:xxx 或者@xxx 绑定所需事件 xxx是事件名称
-2. 事件函数需要配置在methdos属性上,最终也会出现在vm上
-3. methods中配置的函数,都是被Vue所管理的函数,this指代的是vm或者组件实例对象
-4. methods中配置的函数,不要使用带箭头函数,否则this是window
-5. @click="demo" 和@click="demo($event)" 效果一样,只不过后者可以传入其他参数。
-->
<div id="demo">
<h1>我们正在学习{{name}}技术</h1>
<!-- 事件绑定指令: v-on:xxx xxx是事件名称 -->
<button v-on:click="f1()">点我提示信息</button> <br>
<!-- 简化写法: @xxx xxx是事件名称 -->
<button @click="f2()">点我提示信息</button> <br>
<button @click="f3"> 参数:无参的第一种写法,不带括号</button><br>
<button @click="f3()">参数:无参的第二种写法,带括号</button><br>
<!-- 不带括号的写法: 默认传入一个event对象 -->
<button @click="f4">参数:有参, 一个参数</button><br>
<!-- 如果带括号,会默认丢失event参数,需要使用$event来占位, 位置任意 -->
<button @click="f4($event,100,'zhangsan')">参数:有参, 多个参数</button><br>
</div>
<script>
// 该处的定义,Vue模版不能直接访问, vue模版能直接访问Vue实例里的内容
function f1(){
alert("vue是一个构建用户界面的渐进式的javascript框架");
}
const vm = new Vue({
el:"#demo",
data:{
name:"vue",
},
methods:{
f1(){
// alert("vue是一个构建用户界面的渐进式的javascript框架");
//console.log(this); // this是vm实例
},
f2(){
console.log("------调用了f2函数-----");
// this指代的是Vue实例对象
console.log(this)
// 访问Vue实例里的属性name.
console.log(this.name)
},
f3(){
console.log("-----调用了f3函数--------")
},
f4(e,number,name){
console.log(e.target, number,name)
console.log(this)
}
}
})
</script>
2.3.3事件修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件修饰符</title>
<!-- 第一步: 引入vue文件 -->
<script src="../js/vue.js"></script>
<style>
*{
margin: 10px;
}
div{
border: 1px red solid;
padding: 10px;
}
.c1{
width: 200px;
height: 100px;
background-color: aqua;
}
.c2{
width: 100px;
height: 50px;
background-color: yellowgreen;
}
ul{
height: 200px;
padding: 20px;
}
li{
height: 100px;
}
.c3{
width: 200px;
overflow: auto;
background-color: aqua;
}
</style>
</head>
<body>
<!--
Vue中的事件修饰符:
-1. prevent: 阻止默认事件 (常用)
-2. stop: 阻止事件冒泡 (常用)
-3. once: 事件只触发一次 (常用)
-4. capture: 使用事件的捕获模式
-5. self : 只有event.target是当前操作的元素时才触发事件
-6. passive: 事件的默认行为立即执行,无需等待事件回调函数执行完毕
-->
<div id="demo">
<!-- a链接的默认行为是跳转到指定页面, prevent可以阻止默认行为 -->
<a :href="url" @click.prevent="f1()">点我去百度搜索页面</a> <br><br>
<!-- stop修饰词:可以阻止该元素继续向上冒泡的行为 -->
<div class="c1" @click="f1()">
<button @click.stop="f1()">阻止事件冒泡的演示</button> <br>
<!-- 修饰词可以连续添加,顺序无所谓 -->
<a :href="url" @click.stop.prevent="f1()">点我去百度搜索页面</a>
</div>
<!-- once 只会让事件触发一次,再次点击,就不会触发了 -->
<div class="c1">
<button @click.once="f1">事件只触发一次</button>
</div>
<!-- 捕获阶段:从外到内, 事件真正发生阶段从内到外,
如果想要在捕获阶段就调用函数,需要使用修饰词capture
-->
<div class="c1" @click.capture="f2(1)">
<div class="c2" @click="f2(2)">
捕获阶段发生
</div>
</div>
<div class="c1" @click.self="f2(1)">
div1
<div class="c2" @click="f2(2)">
self修饰词
</div>
</div>
<!--
scroll: 滑动鼠标滑轮和拉动滚动条都会触发该事件
wheel: 滑动鼠标滑轮触发, 拉动滚动条不触发
passive: 可以让事件的默认行为立即执行。 bug: 需要添加背景颜色。
-->
<div class="c3" @scroll.passive="f3()">
<ul >
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
</div>
</div>
</body>
<script>
new Vue({
el:"#demo",
data:{
url:"https://www.baidu.com"
},
methods:{
f1(){
alert("同学你好");
},
f2(number){
console.log(number);
console.log(event.target)
},
f3(){
for(var i=0 ; i < 100000; i++){
console.log(10)
}
console.log("终于打印完了")
}
}
})
</script>
</html>
2.3.4键盘事件
<!--
1. 键盘上的每个按键都有自己的名称和编码,例如:Enter(13)。而Vue还对一些常用按键起了别名方便使用
2. Vue中常用的按键别名:
回车:enter
删除:delete (捕获“删除”和“退格”键)
退出:esc
空格:space
换行:tab (特殊,必须配合keydown去使用)
上:up
下:down
左:left
右:right
3. 系统修饰键(用法特殊):ctrl、alt、shift、meta
- 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
- 配合keydown使用:正常触发事件
- 可以使用keyCode去指定具体的按键,比如:@keydown.13="showInfo",但不推荐这样使用
4. Vue.config.keyCodes.自定义键名 = 键码,可以自定义按键别名(不推荐)
-->
2.3.5 内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下2 个:
-
v-text(类似innerText)
-
使用语法:
<p v-text="uname">hello</p>
,意思是将 uame 值渲染到 p 标签中 -
类似 innerText,使用该语法,会覆盖 p 标签原有内容,不能识别HTML标签
-
-
v-html(类似 innerHTML)
-
使用语法:
<p v-html="intro">hello</p>
,意思是将 intro 值渲染到 p 标签中 -
类似 innerHTML,使用该语法,会覆盖 p 标签原有内容,并能将HTML标签的样式呈现出来。
-
<body>
<div id="demo">
v-text的渲染效果: <p v-text="content"></p>
v-html的渲染效果: <p v-html="content"></p>
</div>
</body>
<script>
new Vue({
el: "#demo",
data: {
content: `我是一个 <span> span标签</span>`
}
})
</script>
2.3.6 条件渲染指令
条件判断指令,用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
-
v-show
-
作用: 控制元素显示隐藏
-
语法: v-show = "表达式" 表达式值为 true 显示, false 隐藏
-
原理: 切换 display:none 控制显示隐藏
-
场景:频繁切换显示隐藏的场景
-
-
v-if
-
作用: 控制元素显示隐藏(条件渲染)
-
语法: v-if= "表达式" 表达式值 true显示, false 隐藏
-
原理: 基于条件判断,是否创建 或 移除元素节点
-
场景: 要么显示,要么隐藏,不频繁切换的场景
-
<!--
条件渲染:1. v-if
写法:
(1) v-if="boolean表达式"
(2) v-else-if="boolean表达式"
(3) v-else
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除
注意:v-if可以与v-else-if、v-else一起使用,但要求结构不能被打断
2. v-show
写法:v-show="boolean表达式"
false: 表示不显示,底层本质添加内联样式style="display:none;"
true: 表示显示,底层的本质是去掉了内联样式
适用于:切换频率较高的场景
特点:不展示的DOM元素不是被移除,而是使用dispaly:none进行隐藏
3. 备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到
-->
<div id="demo">
<h1 v-show="s1">欢迎来到{{name}}学习</h1>
<h1 v-if="1===1">欢迎来到{{name}}学习</h1>
<!-- <div>
<h1>n当前的值:{{n}}</h1>
<button @click="n++">点我n+1</button>
<h2 v-if="n===1">java</h2>
<h2 v-if="n===2">c++</h2>
<h2 v-if="n===3">Vue</h2>
</div> -->
<!-- v-else-if指令:
写法:v-else-if="xxx" xxx是条件表达式
逻辑: 写在上面的条件不成立时,才会执行到v-else-if里的条件判断
注意: v-else-if与上面的指令v-if中间不能被其他内容隔断开
-->
<!-- <div>
<h1>n当前的值:{{n}}</h1>
<button @click="n++">点我n+1</button>
<h2 v-if="n===1">java</h2>
<h2>同学你好</h2>
<h2 v-else-if="n===2">c++</h2>
<h2 v-else-if="n===3">Vue</h2>
</div> -->
<!-- v-else:
写法: v-else 后面不用写表达式
逻辑: 上面的条件都不成立时,才会执行v-else
注意: 也不能与上面的v-if、v-else-if中间被其他内容隔断开。 -->
<!-- <div>
<h1>n当前的值:{{n}}</h1>
<button @click="n++">点我n+1</button>
<h2 v-if="n===1">java</h2>
<h2 v-else-if="n===2">c++</h2>
<h2 v-else-if="n===3">Vue</h2>
<h2 v-else>同学你好</h2>
</div> -->
<!--
如果不想破坏结构:
可以使用template标记与v-if进行配合。 注意不能使用v-show
-->
<template v-if="n===2">
<h2 >张三</h2>
<h2 >李四</h2>
<h2 >王五</h2>
</template>
</div>
</body>
<script>
new Vue({
el:"#demo",
data:{
name:"水利电力学院",
s1:true,
n:1
}
})
</script>
2.3.7 列表渲染指令
Vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。
v-for 指令需要使用 (item, index) in arr
形式的特殊语法,其中:
-
item 是数组中的每一项
-
index 是每一项的索引,不需要可以省略
-
arr 是被遍历的数组
此语法也可以遍历对象和数字
<!--
v-for 指令
(1)用于展示列表数据
(2)语法:v-for = "(item, index) in xxx " :key=“yyy”
(3)可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
-->
<!-- 第二步: 准备容器 -->
<div id="demo">
<h1>人员列表</h1>
<ul>
<h1>v-for 遍历数组</h1>
<!-- <li v-for="p of persons">{{p}}</li> -->
<li v-for="(p,index) of persons" :key="index">
{{index}} - {{p}}
</li>
<h1>v-for 遍历对象</h1>
<li v-for="(value,key,index) of student" :key="index">
{{index}} - {{key}} - {{value}}
</li>
<h1>v-for 遍历字符串</h1>
<li v-for="(char,index) of str" :key="index">
{{index}} - {{char}}
</li>
<h1>v-for 遍历数字</h1>
<li v-for="(n,index) of number" :key="index">
{{index}} - {{n}}
</li>
</ul>
</div>
<script>
new Vue({
el:"#demo",
data:{
persons:[
{id:1001,name:"张三",age:30},
{id:1002,name:"李四",age:28},
{id:1003,name:"王五",age:32},
{id:1004,name:"赵六",age:22}
],
student:{id:10001,name:"苏大强",age:58,gender:"男"},
str: "hello",
number:5
}
})
</script>
</html>
v-for中的key
语法: :key="唯一值"
作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用。
为什么加key: 因为Vue在发现数据变化时,会重新渲染页面。这个过程会先生产虚拟DOM。然后和之前的虚拟DOM做比较。原理主要是判断节点的key是否相同,如果相同即继续比较节点里的内容,如果不同,生成新的真实DOM。 相同的地方直接复用上一次的真实DOM.
实例代码:
<body>
<!--
面试题:react、vue中的key有什么作用?
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成新的虚拟DOM
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
--1.若虚拟DOM中内容没变,直接使用之前的真实DOM!
--2.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
--1.创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
(2)如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题。
4.开发中如何选择key?:
(1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
-->
<div id="demo">
<h1>人员列表</h1>
<button @click="add">点我添加一个人员信息</button>
<ul>
<li v-for="(p,index) of persons" :key="p.id">
{{p.id}} - {{p.name}} <input type="text">
</li>
</ul>
</div>
</body>
<script>
new Vue({
el:"#demo",
data:{
persons:[
{id:1001,name:"张三",age:30},
{id:1002,name:"李四",age:28},
{id:1003,name:"王五",age:32}
]
},
methods: {
add(){
var p = {id:1004,name:"赵六",age:22}
// this.persons.unshift(p);
this.persons.push(p)
}
},
})
</script>
注意:
-
key 的值只能是字符串 或 数字类型
-
key 的值必须具有唯一性
-
推荐使用 id 作为 key(唯一),不推荐使用 index 作为 key(会变化,不对应)
2.3.9 额外几个指令
1.v-cloak
<!--
v-cloak:
应用场景:
假如:网络不好, 我们引用的服务端/网络上的vue.js/vue.min.js 在30秒之内还没有加载过来,那么浏览器的页面应该如下效果
"学生姓名{{studentName}}"
也就是说:如果是上述显示效果,那么客户体验度不够好。
作用: vue提供的一个没有值的指令 直接在开始标签里使用
1. 需要配合style样式。一起使用, 如果还没有成功加载js文件,就通过style的属性选择器来隐藏掉该HTMLelement
2. vue在成功加载容器时,如果发现有该指令,就会将该指令从标签中移除。
如何测试: 网络延迟不好演示,那就使用剪切掉script来表示没有加载成功,这样来演示
-->
<body>
<div id="app">
<span v-cloak>学生姓名{{studentName}}</span>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
studentName: "michael"
}
})
</script>
</body>
2.v-once
<!--
v-once:
1.v-once所在节点在初次动态渲染后,就视为静态内容了。
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
-->
<body>
<div id="app">
<button @click="n++">点我n自动加1</button> <br>
<span v-once>n的值为:{{n}}</span> <br>
<span>n的值为:{{n}}</span>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
n: 1
}
})
</script>
</body>
3.v-pre
<!-- v-pre:
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
怎么理解编译: 就是vue在发现某一个节点时,需要去里面查看是否有自己的模版语法,如果有语法,就要替换成实例里的内容
不编译: 就是不去查看是否有自己的模版语法了。
-->
<body>
<div id="app">
<ul>
<li v-pre>员工列表{{schoolName}}</li>
</ul>
<ul>
<span>{{name}}</span>
</ul>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
schoolName: "吉大",
name: "michael"
}
})
</script>
</body>
2.4计算属性
2.4.1 计算属性的学习
从字符串反转这样的练习题中,我们发现
-
插值语法的初衷是用于简单运算。明显练习题中的写法,违背了插值语法的初衷。
-
methods方法可以。但是方法中如果封装的是性能开销比较大的逻辑代码,需要进行大量的运算,并且别的属性还依赖这个方法,那不可避免的是,这个方法可能还要执行很多次。 这种情况,对CPU的性能开销可想而知,有多巨大了。
而Vue引入了计算属性来解决这个问题,它提供了缓存机制。如果重复调用计算属性,就使用缓存数据,提高性能。
完整语法格式:
computed:{
属性名:{
get(){
//提供get方法,1. 初始加载时调用 2.所依赖的值被改变时
}
set(value){
//提供set方法,1. 当对应的计算属性fullName的值主动修改时
}
}
}
简化语法格式: 只有确定 属性为只读时,才能使用简化写法。
computed:{
属性名(){
//....其实是get方法逻辑
}
}
<!--
计算属性:
-1. 定义: 要用的属性不存在,要通过已有属性计算得来
-2. 原理: 底层借助了Object.difineProperty方法提供的getter和setter
-3. get函数什么时候执行
(1) 初次读取时会执行一次
(2) 当依赖的数据发生变化时会再次被调用
-4. 优势: 与methods实现相比,内部有缓存机制(重复使用),效率更高,调试方便
-5. 备注:
(1) 计算属性最终会出现在vm上,直接读取即可。
(2) 如果计算属性要被修改,那必须使用set函数,且set函数中要对计算时所依赖的属性进行修改
-6. 与方法的比较
(1). 计算属性,在调用时不加(),原因:调用的是属性, 重复调用,走缓存
(2). methods方式,在调用时,必须添加(), 原因:调用的是函数,没有缓存机制
-->
2.5 侦听属性
2.5.1 介绍
侦听(监听) 就是对 内置对象的状态或者属性进行监听,如果发生了变化,就做出一些相应的处理操作。
在 Vue.js 中,监视属性是用于观察 Vue 实例中的数据变动的一种机制,当需要在数据变化时执行异步或开销较大的操作时,适合使用监听属性watch
。
语法1:在Vue中添加watch属性
// 完整写法
watch: {
`被监听的属性名`:{
immediate: true, //Vue初始化时,就调用一次回调函数handler
deep:true, //开启深度监听
handler(newValue,oldValue){ //回调函数
//第一个参数,是被监听属性的新值
//第二个参数,是被监听属性的旧值
}
}
}
//简化写法
watch: {
被监听属性名(newValue,oldValue){
//第一个参数,是被监听属性的新值
//第二个参数,是被监听属性的旧值
}
}
}
语法2: 使用vm实例绑定watch方法
vm.$watch("被监听属性名", {
immediate: true,
deep: true,
handler(newValue, oldValue) {
//....
}
})
//简化写法
vm.$watch("被监听属性名",function(newValue,oldValue){
//...
})
当被监视的属性变化时,回调函数自动调用
监视的属性必须存在,才能被监视
案例演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./js/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="weather" placeholder="请输入天气"><br>
<input type="text" v-model="hobbies.hobby1" placeholder="请输入爱好1"><br>
<input type="text" v-model="hobbies.hobby2" placeholder="请输入爱好2"><br>
</div>
</body>
<!-- watch:
1.作用是用来监听vue中已经存在的属性,当监听的属性发生了变化,可以进行一些其他操作,比如异步发送或者性能开销大的操作
2.语法:
第一类:在vue中的配置项上写
new Vue({
data:{},
...,
watch:{
监听的属性名:{
immediate:true,
deep:true,
handler(newValue,oldValue){
//逻辑代码
}
}
})
简化写法:不需要配置 immediate和deep时,可以简写
watch:{
监听的属性名(newValue,oldValue){
//逻辑代码
}
}
第二类:在vue外面写,需要调用vue实例的$watch方法
vm.$watch('要监听的属性名',{配置项})
简写方式: 不需要配置immediate和deep时,可以简写
vm.$watch('要监听的属性名',function(newValue,oldValue){.........})
3.计算属性能做的 监听属性都可以做。
4.一般监听属性用于发送异步请求(比如:搜索功能),而计算属性适合性能开销大的运算逻辑
-->
<script>
const vm = new Vue({
el:"#app",
data:{
weather:"",
hobbies:{
hobby1:"",
hobby2:""
}
},
watch:{
weather:{
//该函数的调用时机,监听的属性发生了变化
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
},
hobbies:{
//vue实例对象初始化时就执行一次
immediate:true,
//开启深度监听,可以监听到属性内部的子属性变化
deep:true,
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
}
}
})
</script>
</html>
2.5.2 计算属性与监视属性的区别
计算属性是依赖的值改变后重新计算结果更新DOM,会进行缓存。
属性监听的是属性值,当定义的值发生变化时,执行相对应的函数。
最主要的用途区别: 计算属性不能执行异步任务。计算属性一般不会用来向服务器请求或者执行异步任务,因为耗时可能会比较长,我们的计算属性要实时更新。所以这个异步任务就可以用监听属性来做。
总而言之:computed能实现的,watch都能实现,computed不能实现的,watch也能实现
2.6生命周期
2.7样式属性练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 第一步: 引入vue文件 -->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
.basic{
border: 1px red solid;
width: 400px;
height: 100px;
}
/* 下面的三个样式,使用其中一个 */
.r1{
border: 10px blue dotted;
background-color: gray;
}
.r2{
border: 10px orange dashed;
background-color: green;
}
.r3{
border: 10px red double;
background-color:burlywood;
}
/* 下面的三种样式,可能会使用其中1个,或者2个,或者三个,或者一个都不用 */
.c1{
font-size: 30px;
font-style: italic;
}
.c2{
border-radius: 20px;
}
.c3{
background: linear-gradient(to right, green,rgb(0, 225, 255));
}
</style>
</head>
<body>
<!-- 绑定样式:
1. class样式
:class="xxx" xxx可以是字符串,对象,数组
-字符串写法适用于:类名不确定,要动态获取
-对象写法适用于:要绑定多个样式,个数确定,名字确定,但是不确定用不用
-数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
2. style样式
:style="{fontSize:xxx}" 其中xxx是动态值
:style="[a,b]" 其中a、b是样式对象
-->
<!-- 第二步: 准备容器 -->
<div id="demo">
<!-- 绑定class样式--字符串写法 ,适用于样式的类名不确定,需要动态指定 --> -->
<div class="basic" :class="classStyle">
欢迎来到{{name}}学习 <br><br>
<button @click="change1">点我改变样式</button>
</div> <br><br>
<!-- 绑定class样式:对象写法,适用于要绑定的样式个数确定,名字确定,但要动态决定用不用 -->
<div class="basic" :class="classObject">
欢迎来到{{name}}学习 <br><br>
</div> <br><br>
<!-- 绑定class样式:数组写法,适用于要绑定的样式个数不确定,名字也不确定 -->
<div class="basic" :class="classArr">
欢迎来到{{name}}学习 <br><br>
</div> <br><br>
<!-- 绑定style样式: 对象写法 -->
<div class="basic" :style="styleObject">
欢迎来到{{name}}学习 <br><br>
</div> <br><br>
<!-- 绑定style样式: 数组写法 -->
<div class="basic" :style="styleArr">
欢迎来到{{name}}学习 <br><br>
</div> <br><br>
</div>
</body>
<script>
// 第三步: 创建Vue实例
new Vue({
// 第四步: 设置挂载点, 以及配置数据
el:"#demo",
data:{
name:"水利电力学院",
classStyle:"",
// index:0,
classObject:{
c1:false,
c2:true,
c3:true
},
classArr:['c1','c2','c3'],
styleObject:{
fontSize:'40px',
backgroundColor:"red"
},
styleArr:[
{fontSize:'40px'},
{backgroundColor:"blue"}
]
},
methods: {
change1(){
var arr = ["r1","r2","r3"]
var index = Math.floor(Math.random()*3)
this.classStyle = arr[index]
}
},
})
</script>
</html>