7 - Vue学习笔记 -计算属性、ES6 语法补充

本文探讨了Vue中的计算属性,包括其基本使用、setter和getter,以及与methods的区别。通过示例展示了计算属性如何简化代码并提高性能。此外,还补充了ES6的let和var的区别,强调let的块级作用域特性,以及const的使用场景和注意事项,提倡在开发中优先使用const。
摘要由CSDN通过智能技术生成

计算属性

计算属性的基本使用

我们直到,在模板可以直接通过插值语法显示一些 data 里的数据
但是在某些情况下,我们可能需要对数据先进行转换后再显示,或者需要多个数据结合起来进行显示

  • 比如我们有 firstNamelastName 两个变量,我们需要显示完整的名称
  • 但是如果多个地方都要显示完整的名称,使用以前的方法就需要写多个 {{firstName}} {{lastName}}

因此,为了方便阅读
我们可以将上面的代码换成计算属性:

  • 计算属性是写在实例的 computed 选项中的
  • 另外我们会发现,虽然我们在 computed 里面定义的是一个方法,但是在调用时并没有显式得调用该方法,Vue 在这里面帮我们做了很多优化。因此,虽然在 methods 中也可以定义相同的方法,但是调用起来会更复杂,而且性能没有 computed 里的高, computed 里的只会调用一次,会有缓存数据,性能会提高。
 <div id="app">
 	<!-- 以前的方法 -->
	<h2>{{firstName + ' ' + lastName}}</h2>
	<h2>{{firstName}} {{lastName}}</h2>
	
	<h2>{{getFullName()}}</h2>
	
	<h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
	const app = new Vue({
		el: "#app",
		data: {
			firstName: 'Lebron',
			lastName: 'James'
		},
		// computed: 计算属性() 命名最好以属性命名,不用加动词,比如 get..
		computed: {
			fullName: function () {
				return this.firstName + ' ' + this.lastName;
			}
		},
		methods: {
			getFullName() {
				return this.firstName + ' ' + this.lastName;
			}
		}
	});
</script>

再比如一个案例,我们有一些书,想要展示他们的价格和

data: {
	books: [
		{id: 110, name: "Unix编程艺术", price: 119},
		{id: 111, name: "代码大全", price: 105},
		{id: 112, name: "深入理解计算机原理", price: 90},
		{id: 113, name: "现在操作系统", price: 89},
	]
}
--- ... ---
computed: {
	totalPrice: function () {
		let result = 0;
		for (let i = 0; i < this.books.length; i++) {
			result += this.books[i].price;
		}
		return result;
	}
}

这样我们就可以通过 {{totalPrice}} 很方便简洁的得到了总价格


计算属性的 setter 和 getter

data: {
	firstName: 'Kobe',
	lastName: 'Bryant'
	},
computed: {
	// 这个方法是缩写的
	/*fullName: function () {
		return this.firstName + ' ' + this.lastName
	}*/
		
	// 属性,属性有 get 和 set 方法
	fullName: {
		set: function () {
			// 一般情况,计算属性不需要 set 方法,只读
			// 所以都不设置 set 方法,因为我们一般情况不希望改变值
			// 所以一般情况都不写,只写 get 也是不会报错的, 所以 Vue 提供了更加简便的方法设置
			// 也就是之前那种写法,这也就是为什么我们可以通过那样得到值,其实是一个 getter 方法
		},
		get: function () {
			return this.firstName + ' ' + this.lastName
		}
	}

set 的用法如下:

fullName: {
		// 我们可以设置 fullName 的值(通过控制台访问该属性并赋值),这个时候就会调用 set 方法
		// set 方法通过传递一个参数,将修改后的值传递到 set 方法,我们就可以对 fullName 的真实值进行变更,从而达到设置值的目的
		set: function (newValue) {
			console.log('----', newValue); // 当 fullName 发生改变时,会调用 set 方法,可以在控制台看到该语句输出
			const names = newValue.split(' ');
			this.firstName = names[0];
			this.lastName = names[1];
		},
		get: function () {
			return this.firstName + ' ' + this.lastName;
		}
	}

methods 与 computed 的对比

<div id="app">
	<!-- 1. 直接拼接:语法过于繁琐	-->
	<h2>{{firstName}} {{lastName}}</h2>
	<!-- 2. 通过定义 methods,调用四次用于测试	-->
	<h2>{{getFullName()}}</h2>
	<h2>{{getFullName()}}</h2>
	<h2>{{getFullName()}}</h2>
	<h2>{{getFullName()}}</h2>
	<!-- 3. 通过 computed,调用四次用于测试	-->
	<h2>{{fullName}}</h2>
	<h2>{{fullName}}</h2>
	<h2>{{fullName}}</h2>
	<h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
	const app = new Vue({
		el: "#app",
		data: {
			firstName: 'Kobe',
			lastName: 'Bryant'
		},
		methods: {
			getFullName() {
				console.log('getFullName'); // 被打印 4 次,调用 4 次
				return this.firstName + ' ' + this.lastName;
			}
		},
		computed: {
			fullName: function () {
				console.log('fullName'); // 只被打印一次,调用 1 次,有做缓存
				// 只要 firstName 和 lastName 不变,就不会再调用 fullName 了
				return this.firstName + ' ' + this.lastName;
			}
		}
	});
</script>
  • 由上面的实验我们可以得出结论,当我们需要对数据进行一些处理后再展示时,我们可以使用 computed ,他会对数据进行缓存,只要基本的数据不发送改变,就不会被调用多次。假设在数据处理时,使用到了多个循环,那么 methods 每调用一次性能都差很多!

ES6 语法补充

let / var

事实上 var 的设计可以看成 JavaScript 语言设计上的错误,但是这种错误多半不能修复和移除,因为需要向后兼容。
所以大概十年前, Brendan Eich 就决定修复这个问题,于是他添加了一个新的关键字: let
我们可以将 let 看成更完美的 var

块级作用域

let 是有块级作用域的
JavaScript 中使用 var 来声明一个变量时,变量的作用域主要是和函数的定义有关
针对于其他块定义来说是没有作用域的,比如 if / for,这在我们开发中往往会引起一些问题

<script>
	// ES5 中的 var 是没有块级作用域的
	// 1. 变量作用域:变量在什么范围内是可用。
	{
		var name = 'why';
		console.log(name)
		// 在很多编程语言中,代码块里面的变量,外面是无法访问的
	}
	console.log(name);// 这咯i也可以访问 name

	// 2. 没有块级作用域引起的问题, if 的块级
	var func;
	
	if (true) {
		var name = 'why';
		func = function () {
			console.log(name)
		}
	}
	// func 的作用是打印 if 里面 name 的值
	// 很多情况下,我们是把 name 封装到 if 等其他代码块里面
	// 我们不希望外面的人能够修改他们,但是 var 会让外面也可以访问
	name = 'kobe';
	func();
</script>

<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>

<script>
	// 2. 没有块级作用域引起的问题, for 的块级
	// 假设我们需要,点击第几个按钮,就在控制台打印第几个按钮被点击
	// 我们以前会这样做
	var btns = document.getElementsByTagName('button');
	for (var i = 0; i < btns.length; i++) {
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	// 我们会发现,我们点哪一个按钮,都是第5个按钮被点击
	// 因为这个 i 其实是一个全局变量,i 一被更改,所有使用到 i 的地方,都被修改
	// 解决办法
	for (var i = 0; i < btns.length; i++) {
		(function (num) {
			btns[i].addEventListener('click', function () {
				console.log('第' + num + '个按钮被点击');
			})
		})(i)
	}
	// 因为 在 JavaScript 中函数是有作用域的,所以把 i当作一个参数传递进去
	// 这样值就不会被随便修改
	
	// 在 ES5 之前,因为 if 和 for 都没有块级作用域的概念,
	// 所以在很多时候,我们都必须借助于 function 的作用域来解决应用外面变量的问题
	// ES6 中,加入了 let,它在 if 和 for 中有块级作用域的概念
	const btns = document.getElementsByTagName('button');
	for (let i = 0; i < btns.length; i++) {
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	// 这样就可以成功,并且简洁
</script>

伪代码分析:

<script>
	var btns = document.getElementsByTagName('button');
	for (var i = 0; i < btns.length; i++) {
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	// 1. 情况一: ES5 中没有使用闭包
	{
		i = 0;
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	{
		i = 1;
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	{
		i = 2;
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	// 因为 var 没有作用域,本来应该使用自己各自的 i
	// 结果每一个代码块中的 i 都是一样的
	
	
	for (var i = 0; i < btns.length; i++) {
		(function (num) {
			btns[i].addEventListener('click', function () {
				console.log('第' + num + '个按钮被点击');
			})
		})(i)
	}
	
	// 2. 情况二: ES5 使用闭包
	// 因为函数是有作用域的,所以这个 i 当作一个参数传入,这样每个函数体内部都有一个属于自己的 num
	function (num) { // i = 0 -> num = 0
		btns[i].addEventListener('click', function () {
			console.log('第' + num + '个按钮被点击');
		})
	}(i)
	function (num) { // i = 1 -> num = 1
		btns[i].addEventListener('click', function () {
			console.log('第' + num + '个按钮被点击');
		})
	}(i)
	function (num) { // i = 2 -> num = 2
		btns[i].addEventListener('click', function () {
			console.log('第' + num + '个按钮被点击');
		})
	}(i)
	
	
	
	const btns = document.getElementsByTagName('button');
	for (let i = 0; i < btns.length; i++) {
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	
	// 3. 情况三:ES6 let
	{
		i = 0; // 每个大括号有属于自己的 i
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	{
		i = 1;
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
	{
		i = 2;
		btns[i].addEventListener('click', function () {
			console.log('第' + i + '个按钮被点击');
		})
	}
</script>

const 的使用

const 关键字在很多语言都存在,主要的作用是将某个变量修饰为常量,不再对它进行更改。
JavaScript 也是如此
什么时候使用 const
当我们修饰的标识符不会被再次赋值时,可以使用 const 来保证数据的安全性

  1. 注意一:
const a = 20;
a = 30; // 错误,不可以修改
  1. 注意二:
const name; // 错误,const 修饰的标识符必须赋值
  • 建议:在 ES6 开发中,优先使用 const,只有需要改变某个标识符的时候才使用 let
  1. 注意三:
// 常量的含义是指向的对象不能修改,但是可以改变对象内部的属性
const obj = {
	name: 'why',
	age: 18,
	height: 1.88
}
	
console.log(obj);
	
obj.name = 'kobe';
obj.age = 40;
obj.height = 1.87;
	
console.log(obj);

保存对象的时候其实是保存对象的地址,所以这个地址不能更改

对象的增强写法
<script>
	// 1. 属性的增强写法
	const name = 'why';
	const age = 18;
	const height = 1.88;
	// 假设我们需要把 这些属性放进一个对象,之前是这样做的
	// ES5 写法
	/*
	const obj = {
		name: name,
		age: age,
		height: height
	}
	 */
	// ES6 写法, 在内部会把变量名作为 key,变量的值作为 value
	const obj = {
		name,
		age,
		height
	}
	console.log(obj);
	
	// 2. 函数的增强写法
	// ES5 写法
	/*
	const obj1 = {
		run: function () {
		
		},
		eat: function () {
		
		}
	}
	 */
	// ES6 写法
	const obj1 = {
		run() {
		
		},
		eat() {
		
		}
	}
	// 这样语法更简单
</script>
单链表的基本操作 1.实验题目 问题描述:实现带头结点的单链表的建立、求长度,取元素、修改元素、插入、删除 等单链表的基本操作。通过代码的编写理解并掌握单链表的过程编写以及作用。 2.实验要求 (1)依次从键盘读入数据,建立一个单链表并将单链表的初始化设置为空; (2)通过操作选择,输出单链表中的数据元素 (3)显示单链表的长度; (4)根据指定条件能够查找出元素和修改元素; (5)实现在指定位置插入和删除元素的功能 (6)显示操作后的结果 3.算法设计 (1)用到的结构(逻辑结构、存储结构) 逻辑结构:线性结构 存储结构:带头结点的单链表 (2)算法设计思路 定义结点类型LNode,每个结点包括数据域data和指针域next。定义头指针LinkList 。编写如下函数: 1、createlist(LinkList &L);用尾插法创建一个带头结点的单链表。 2、print(LinkList L);输出该单链表中的数据元素。 3、ListLength(LinkList L);求该单链表的长度。 4、GetElem(LinkList &L,int i,ElemType &e);查找第i个元素。 5、SetElem(LinkList &L,int i,ElemType m);修改第i个元素。 6、ListInsert (LinkList &L, int i, ElemType e );在第i个元素前插入一个元素。7、ListDelete(LinkList &L,int i,ElemType &e2);删除第i个元素。 8、main();通过case结构来调用createlist(LinkList &L)、GetElem(LinkList &L,int i,ElemType &e)、SetElem(LinkList &L,int i,ElemType m)、ListInsert (LinkList &L, int i, ElemType e )、ListDelete(LinkList &L,int i,ElemType &e2) 4.调试和测试 调试过程总结经过多次调试,本程序能很好的完成实验要求的各项功能。给出几组测 试数据及实验结果: 4.1 系统界面 4.2 创建带头结点的单链表 (先输入单链表整数,每输入完一个整数后按回车键,数据输入完后以0结束) 4.3 打印链表中的数据 4.4 打印链表长度 4.5 按位置取元素 4.6 修改链表中的元素 4.7 插入结点 4.8 按结点位置编号删除结点 4.8 显示做了修改后的链表元素: 5.实验总结 对比这次试验,在上机的时候明显感觉到比之前更加有思路,能够很好地找个关键性 的语句对程序进行修改,这次试验虽然说比上次好,但是也暴漏出了许多的缺陷,在编 写的时候,感觉整个流程都挺对,但是就是运行不出来,或者是不能够实现原有的功能 ,通过与同学的交流,然后慢慢地参照课本才将本次试验很好地完成。 6.附录(源程序) #include<stdio.h> #include<conio.h> #include"stdafx.h" #define OK 1 #define ERROR 0 typedef char ElemType; typedef int Status; typedef struct LNode { ElemType data; LNode *next; } LNode,*LinkList; Status createlist(LinkList &L) //尾插法创建带头结点的单链表 { int ch; L=new LNode; L->next=NULL; printf("请输入单链表中的数据:"); scanf("%d", &ch); LinkList r=L; while(ch!=0) { LinkList p=new LNode; p->data=ch; p->next=NULL; r->next=p; r=p; scanf("%d", &ch); } return OK; } void print(LinkList L) //输出单链表 { LinkList p=L->next; printf("单链表为:\n"); while(p) { printf("%2d",p->data); p=p->next; }} Status ListLength(LinkList L) //求单链表的长度 { int k=0; LinkList p=L->next; while(p){ k++; p=p->next;} printf("\n"); printf("单链表的长度为 %d:" , k); printf("\n"); return k; } Status GetElem(Lin 单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据元素和指向下一个节点的指针。在这个实验报告中,重点是实现带头结点的单链表的基本操作,包括建立、求长度、取元素、修改元素、插入和删除等。 实验题目要求从键盘读入数据来构建一个单链表,并初始化为空。这意味着我们需要编写一个函数来创建链表,例如`createlist`函数,该函数使用尾插法,即每次新输入的数据会被添加到链表的末尾。这可以通过循环读取用户输入,创建新的节点并将其连接到现有链表的末尾来实现。 实验要求能够输出链表中的数据元素,这可以通过`print`函数完成。此函数遍历链表,打印每个节点的数据域。 另外,链表的长度可以通过`ListLength`函数计算,该函数遍历整个链表,每次遇到一个节点就增加计数器,最后返回计数值。 查找和修改元素的功能由`GetElem`和`SetElem`函数提供。`GetElem`用于获取指定位置的元素,而`SetElem`则用于修改这个位置的元素值。这两个函数都需要处理非法索引的情况,例如索引超出链表范围。 此外,实验还需要实现插入和删除操作。`ListInsert`函数在给定位置插入新元素,而`ListDelete`函数删除指定位置的元素。这两种操作都需要在链表中找到正确的位置,然后调整指针以保持链表的连续性。 在实验的调试和测试阶段,作者通过输入不同数据和执行各种操作来验证程序的正确性,并针对出现问题的地方进行了修改和完善。 实验总结部分,作者提到这次实验相比以前更有思路,能够更有效地修改程序,但也暴露了编程过程中的一些不足,如逻辑错误或功能不完全实现。这些问题通过与同学的交流和参考教材得到了解决。 源代码部分展示了实现这些功能的C语言结构,包括定义链表节点类型`LNode`,头指针`LinkList`,以及上述各函数的定义。这些函数实现了链表操作的核心逻辑。 这个实验旨在加深对单链表的理解,包括其基本操作的实现细节和问题解决过程,这对于学习数据结构和算法至关重要。通过这样的实践,可以提高对链表这种数据结构的实际运用能力。。内容来源于网络分享,如有侵权请联系我删除。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值