作者:故事我忘了
个人微信公众号:程序猿的月光宝盒

一. 计算属性

1.1. 计算属性的本质

  • 每个计算属性都包含一个getter和一个setter

  • 一般情况下我们写的都是getter方法

  • 在某些情况下,你也可以提供一个setter方法(不常用)

  • 在需要写setter的时候,代码如下

1.2. 计算属性和methods对比

methods和computed看起来都可以实现我们的功能,

那么为什么还要多一个计算属性这个东西呢?

原因:

  • 计算属性在多次使用时, 只会调用一次.

  • 它是有缓存的

〇.ES6补充

0.1. let/var

事实上var的设计可以看成JavaScript语言设计上的错误. 但是这种错误多半不能修复和移除, 以为需要向后兼容.

​ 大概十年前, Brendan Eich就决定修复这个问题, 于是他添加了一个新的关键字: let.

​ 我们可以将let看成更完美的var

块级作用域

​ JS中使用var来声明一个变量时, 变量的作用域主要是和函数的定义有关.

​ 针对于其他块定义来说是没有作用域的,比如if/for等,这在我们开发中往往会引起一些问题。

而在for中使用var时,我们往往需要这样,因为在ES5中 var 只有function有作用域

但是在ES6后,用let就简单多了

0.2 const的使用

const这个关键字

​ 在很多语言中已经存在, 比如C/C++中, 主要的作用是将某个变量修饰为常量.

​ 在JavaScript中也是如此, 使用const修饰的标识符为常量, 不可以再次赋值.

什么时候使用?

​ 修饰的标识符不会被再次赋值时, 就可以使用const来保证数据的安全性.

0.2.1. 人生建议

在ES6开发中,优先使用const, 只有需要改变某一个标识符的时候才使用let.

使用注意点

const a = 20;
a = 30; //错误:不可以被修改
const name;//错误:没有赋值

0.3 对象字面量增强写法

​ ES6中,对对象字面量进行了很多增强。

​ 属性初始化简写和方法的简写:

二. 事件监听 v-on

v-on介绍

作用:绑定事件监听器

语法糖:@

预期:Function | Inline Statement | Object

参数:event

2.1. 事件监听基本使用

这里,我们用一个监听按钮的点击事件,来简单看看v-on的使用

​ 下面的代码中,使用了v-on:click="counter++”

​ 另外,我们可以将事件指向一个在methods中定义的函数

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<h2>{{counter}}</h2>
<!--<h2 v-bind:title></h2>-->
<!--<h2 :title></h2>-->
<!--<button v-on:click="counter++">+</button>-->
<!--<button v-on:click="counter--">-</button>-->
<!--<button v-on:click="increment">+</button>-->
<!--<button v-on:click="decrement">-</button>-->
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
})
</script> </body>
</html>

2.2. 参数问题

  • btnClick
  • btnClick(event)
  • btnClick(abc, event) -> $event 传入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<!--1.事件调用的方法没有参数-->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮1</button> <!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法-->
<!--<button @click="btn2Click(123)">按钮2</button>-->
<!--<button @click="btn2Click()">按钮2</button>-->
<button @click="btn2Click">按钮2</button> <!--3.方法定义时, 我们需要event对象, 同时又需要其他参数-->
<!-- 在调用方式, 如何手动的获取到浏览器参数的event对象: $event-->
<button @click="btn3Click(abc, $event)">按钮3</button>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
abc: 123
},
methods: {
btn1Click() {
console.log("btn1Click");
},
btn2Click(event) {
console.log('--------', event);
},
btn3Click(abc, event) {
console.log('++++++++', abc, event);
}
}
}) // 如果函数需要参数,但是没有传入, 那么函数的形参为undefined
// function abc(name) {
// console.log(name);
// }
//
// abc()
</script>
</body>
</html>

2.3. 修饰符

  • .stop 调用 event.stopPropagation() 停止冒泡

  • .prevent 阻止默认行为

  • .enter 键修饰符,键别名

  • .once 只监听一次

  • .native 监听组件根元素的原生事件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<!--1. .stop修饰符的使用,调用 event.stopPropagation() 就是点了之后不显示点div-->
<div @click="divClick">
aaaaaaa
<button @click.stop="btnClick">按钮</button>
</div> <!--2. .prevent修饰符的使用 调用 event.preventDefault() 阻止默认行为,以下 是阻止表单默认提交-->
<br>
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form> <!--3. .监听某个键盘的键帽,这里是监听回车按键 把回车按键去掉就都监听了-->
<input type="text" @keyup.enter="keyUp"> <!--4. .once修饰符的使用 只触发一次回调-->
<button @click.once="btn2Click">按钮2</button>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
btnClick() {
console.log("btnClick");
},
divClick() {
console.log("divClick");
},
submitClick() {
console.log('submitClick');
},
keyUp() {
console.log('keyUp');
},
btn2Click() {
console.log('btn2Click');
}
}
})
</script>
</body>
</html>

三. 条件判断

3.1. v-if/v-else-if/v-else

​ 这三个指令与JavaScript的条件语句if、else、else if类似。

​ Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件

简单案例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>不及格</h2>
<!--计算属性 直接计算好了返回 不写在dom里-->
<h1>{{result}}</h1>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 99
},
computed: {
result() {
let showMessage = '';
if (this.score >= 90) {
showMessage = '优秀'
} else if (this.score >= 80) {
showMessage = '良好'
}
// ...
return showMessage
}
}
})
</script>
</body>
</html>

v-if的原理:

​ v-if后面的条件为false时,对应的元素以及其子元素不会渲染。

​ 也就是根本不会有对应的标签出现在DOM中。

3.2. 登录小案例

用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模拟登录方式切换</title>
</head>
<body>
<div id="vm">
<div v-if="showTag">
<label for="userName">用户账号</label>
<input id="userName" placeholder="用户账号">
<!--<input id="userName" placeholder="用户账号" key="name">-->
</div>
<div v-else>
<label for="userMail">用户邮箱</label>
<input id="userMail" placeholder="用户邮箱">
<!--<input id="userMail" placeholder="用户邮箱" key="email">-->
</div>
<button @click="showTag = !showTag">切换登录方式</button>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el:'#vm',
data:{
showTag:true
}
})
</script>
</html>

小问题:

​ 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。

​ 但是按道理讲,我们应该切换到另外一个input元素中了。

​ 在另一个input元素中,我们并没有输入内容。

为什么会出现这个问题呢?

​ 问题解答:

​ 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。

​ 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。

​ 解决方案:

如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key

并且我们需要保证key的不同

3.3. v-show

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<!--v-if: 当条件为false时, 包含v-if指令的元素, 根本就不会存在dom中-->
<h2 v-if="isShow" id="aaa">{{message}}</h2> <!--v-show: 当条件为false时, v-show只是给我们的元素添加一个行内样式: display: none-->
<h2 v-show="isShow" id="bbb">{{message}}</h2>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isShow: true
}
})
</script> </body>
</html>

v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:

v-if和v-show对比

​ 相同:

v-ifv-show都可以决定一个元素是否渲染

​ 不同:

v-if当条件为false时,压根不会有对应的元素在DOM中。

v-show当条件为false时,仅仅是将元素的display属性设置为none而已。

开发中如何选择呢?

​ 当需要在显示与隐藏之间切换频繁时,使用v-show

​ 当只有一次切换时,通过使用v-if

四. 循环遍历

4.1. 遍历数组

当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。

​ v-for的语法类似于JavaScript中的for循环。

​ 格式如下:item in items的形式。

如果在遍历的过程中不需要使用索引值

​ v-for="movie in movies"

​ 依次从movies中取出movie,并且在元素的内容中,我们可以使用Mustache语法,来使用movie

如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?

​ 语法格式:v-for=(item, index) in items

​ 其中的index就代表了取出的item在原数组的索引值。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<!--1.在遍历的过程中,没有使用索引值(下标值)-->
<ul>
<li v-for="item in names">{{item}}</li>
</ul> <!--2.在遍历的过程中, 获取索引值-->
<ul>
<li v-for="(item, index) in names">
{{index+1}}.{{item}}
</li>
</ul>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
names: ['why', 'kobe', 'james', 'curry']
}
})
</script> </body>
</html>

4.2. 遍历对象中的属性

比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来。

  • value

  • value, key

  • value, key, index

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body> <div id="app">
    <!--1.在遍历对象的过程中, 如果只是获取一个值, 那么获取到的是value-->
    <ul>
    <li v-for="item in info">{{item}}</li>
    </ul> <!--2.获取key和value 格式: (value, key) -->
    <ul>
    <li v-for="(value, key) in info">{{value}}-{{key}}</li>
    </ul> <!--3.获取key和value和index 格式: (value, key, index) -->
    <ul>
    <li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
    </ul>
    </div> <script src="../js/vue.js"></script>
    <script>
    const app = new Vue({
    el: '#app',
    data: {
    info: {
    name: 'kin',
    age: 18,
    height: 1.88
    }
    }
    })
    </script> </body>
    </html>

    官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。

    ​ 为什么需要这个key属性呢(了解)?

    ​ 这个其实和Vue的虚拟DOM的Diff算法有关系。

    ​ 这里我们借用React’sdiff algorithm中的一张图来简单说明一下:

    ​ 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点

    ​ 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。

    ​ 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

    ​ 所以我们需要使用key来给每个节点做一个唯一标识

    ​ Diff算法就可以正确的识别此节点

    ​ 找到正确的位置区插入新的节点。

    所以一句话,key的作用主要是为了高效的更新虚拟DOM。

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body> <div id="app">
    <ul>
    <li v-for="item in letters" :key="item">{{item}}</li>
    </ul>
    </div> <script src="../js/vue.js"></script>
    <script>
    const app = new Vue({
    el: '#app',
    data: {
    letters: ['A', 'B', 'C', 'D', 'E']
    }
    })
    </script> </body>
    </html>

4.3. 数组哪些方法是响应式的

push():在最后面添加元素

unshift():在数组最前面添加元素

pop():删除数组中的最后一个元素

shift():删除数组中的第一个元素

splice():删除,插入,替换

sort() :排序

reverse():倒序

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<ul>
<li v-for="item in letters">{{item}}</li>
</ul>
<button @click="btnClick">按钮</button>
</div> <script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['a', 'b', 'c', 'd']
},
methods: {
btnClick() {
// 1.push方法在最后面添加元素
// this.letters.push('aaa')
// this.letters.push('aaaa', 'bbbb', 'cccc') // 2.pop(): 删除数组中的最后一个元素
// this.letters.pop(); // 3.shift(): 删除数组中的第一个元素
// this.letters.shift(); // 4.unshift(): 在数组最前面添加元素
// this.letters.unshift()
// this.letters.unshift('aaa', 'bbb', 'ccc') // 5.splice作用: 删除元素/插入元素/替换元素
// 第一个参数,index开始位置
// 删除元素: 第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)
// 替换元素: 第二个参数, 表示我们要替换几个元素,
// 后面的参数:用于替换前面的元素
// 插入元素: 第二个参数, 传入0,
// 后面的参数:要插入的元素
// splice(start)
// splice(start):
this.letters.splice(1, 3, 'm', 'n', 'l', 'x')
// this.letters.splice(1, 0, 'x', 'y', 'z') // 6.sort() 排序
// this.letters.sort() // 7.reverse() 倒序
// this.letters.reverse() // 注意: 通过索引值修改数组中的元素
// this.letters[0] = 'bbbbbb';
// this.letters.splice(0, 1, 'bbbbbb')
// set(要修改的对象, 索引值, 修改后的值)
// Vue.set(this.letters, 0, 'bbbbbb')
}
}
}) // function sum(num1, num2) {
// return num1 + num2
// }
//
// function sum(num1, num2, num3) {
// return num1 + num2 + num3
// }
// function sum(...num) {
// console.log(num);
// }
//
// sum(20, 30, 40, 50, 601, 111, 122, 33) </script> </body>
</html>

五. 书籍购物车案例

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="vm">
<!--判断有没有长度,没有就是空的-->
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>书名</th>
<th>单价</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<!--showPrice 是过滤器-->
<td>{{item.price | showPrice}}</td>
<td>
<!--v-bind:disabled 条件true时 让按钮失效-->
<button @click="sub(index)" v-bind:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="add(index)">+</button>
</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<h2>总价格:{{totalPrice | showPrice}}</h2>
</div> <h2 v-else>购物车为空</h2>
</div>
</body>
<script src="../js/vue.js"></script>
<script src="main.js"></script>
</html>

main.js

const vm = new Vue({
el:'#vm',
data:{
books:[
{
id: 1,
name:'「人間失格」',
price: 85.42,
count:1
},
{
id: 2,
name:'「白夜行」',
price: 89.00,
count:1
},
{
id: 3,
name:'「解忧杂货铺」',
price: 65.00,
count:1
},
{
id: 4,
name:'「天龙八部」',
price: 185.00,
count:1
}
]
},
methods:{
sub(index){
this.books[index].count--
},
add(index){
this.books[index].count++
},
remove(index){
this.books.splice(index,1)
}
},
computed:{
totalPrice(){
let totalPrice = 0;
for (let book of this.books){
totalPrice += book.price * book.count
}
return totalPrice;
}
},
//过滤器
filters:{
// 自动把参数传进来
showPrice(price){
// .toFixed(2)保留两位小数
return '¥' + price.toFixed(2)
}
}
});

index.css

table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th, td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}

点我进演示地址(外服,有点慢)

Vue 学习笔记 [Part 2]的更多相关文章

  1. Vue学习笔记-2

    前言 本文非vue教程,仅为学习vue过程中的个人理解与笔记,有说的不正确的地方欢迎指正讨论 1.computed计算属性函数中不能使用vm变量 在计算属性的函数中,不能使用Vue构造函数返回的vm变 ...

  2. Vue学习笔记-1

    前言 本文不是Vue.js的教程,只是一边看官网Vue的教程文档一边记录并总结学习过程中遇到的一些问题和思考的笔记. 1.vue和avalon一样,都不支持VM初始时不存在的属性 而在Angular里 ...

  3. vue 学习笔记(二)

    最近公司赶项目,一直也没时间看 vue,之前看下的都快忘得差不多了.哈哈哈,来一起回顾一下vue 学习笔记(一)后,继续向下看嘛. #表单输入绑定 基础用法 v-model 会忽略所有表单元素的 va ...

  4. vue学习笔记之:为何data是一个方法

    vue学习笔记之:为何data是一个方法 在vue开发中,我们可以发现,data中的属性值是在function中return出来的.可为何data必须是一个函数呢?我们先看官方的解释: 当一个组件被定 ...

  5. vue学习笔记(八)组件校验&通信

    前言 在上一章博客的内容中vue学习笔记(七)组件我们初步的认识了组件,并学会了如何定义局部组件和全局组件,上一篇内容仅仅只是对组件一个简单的入门,并没有深入的了解组件当中的其它机制,本篇博客将会带大 ...

  6. vue学习笔记(九)vue-cli中的组件通信

    前言 在上一篇博客vue学习笔记(八)组件校验&通信中,我们学会了vue中组件的校验和父组件向子组件传递信息以及子组件通知父组件(父子组件通信),上一篇博客也提到那是对组件内容的刚刚开始,而本 ...

  7. vue学习笔记(十)路由

    前言 在上一篇博客vue学习笔记(九)vue-cli中的组件通信内容中,我们学习组件通信的相关内容和进行了一些组件通信的小练习,相信大家已经掌握了vue-cli中的组件通信,而本篇博客将会带你更上一层 ...

  8. AntDesign vue学习笔记(七)Form 读写与图片上传

    AntDesign Form使用布局相比传统Jquery有点繁琐 (一)先读写一个简单的input为例 <a-form :form="form" layout="v ...

  9. Vue学习笔记十三:Vue+Bootstrap+vue-resource从接口获取数据库数据

    目录 前言 SpringBoot提供后端接口 Entity类 JPA操作接口 配置文件 数据库表自动映射,添加数据 写提供数据的接口 跨域问题 前端修改 效果图 待续 前言 Vue学习笔记九的列表案例 ...

  10. vue学习笔记(三)class和style绑定

    前言 通过上一章的学习vue学习笔记(二)vue的生命周期和钩子函数,我们已经更近一步的知道了关于vue的一些知识,本篇博客将进一步探讨vue其它方面的内容,vue中关于class和style绑定,关 ...

随机推荐

  1. JMeter 通过 BeanShell 脚本处理入参和回参

    入参:可以通过该方式动态生成入参参数,如时间参数,随机参数等. 操作:右键 HTTP Request - Add - Pre Processor - BeanShell PreProcessor im ...

  2. Golang 入门 : 符文

    字符串常用语表示一系列文本字符,而Go的符文(rune)则用于表示单个字符. 字符串字面量由双引号(")包围,但rune字面量由单引号(')包围. Go程序几乎可以使用地球上任何语言的任何字 ...

  3. 在 Hugging Face Spaces 上使用 Gradio 免费运行 ComfyUI 工作流

    简介 在本教程中,我将逐步指导如何将一个复杂的 ComfyUI 工作流转换为一个简单的 Gradio 应用程序,并讲解如何将其部署在 Hugging Face Spaces 的 ZeroGPU 无服务 ...

  4. 【python-数据分析】pandas数据提取

    import pandas as pd 1. 直接索引 df = pd.DataFrame({'AdmissionDate': ['2021-01-25','2021-01-22','2021-01- ...

  5. 【Linux】3.4 用户管理

    用户管理 1. 基本用户管理 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统. 用户的账号一方面可以帮助 ...

  6. 【Ubuntu】Ubuntu 配置镜像源(ARM)

    [Ubuntu]Ubuntu 配置镜像源(ARM) 零.起因 最近在QEMU中安装了个ubuntu-24.04-live-server-arm64,默认是国外的软件源,很慢,故替换到国内. 壹.替换 ...

  7. datasnap的Restful的接口方法

    //Restful接口测试 //GET function Test(Value: string): string; //POST function updateTest(Value: string; ...

  8. Hello, PostgreSQL

    Hello, PostgreSQL Whoami:5年+金融.政府.医疗领域工作经验的DBA Certificate:PGCM.OCP.YCP Skill:Oracle.Mysql.PostgreSQ ...

  9. exe4j工具使用-jar包转exe可执行文件

    exe4j介绍 exe4j可以将java打包的jar包转为exe可执行文件,实现在没有jdk环境下运行jar包. 下载链接 https://pan.baidu.com/s/1sfEJyxPABmhsl ...

  10. 自定义vscode 调试控制台字体颜色

    "workbench.colorCustomizations": { "debugConsole.warningForeground": "#1818 ...