JavaScript
您现在的位置是:博客主页 > Web教程 > JavaScript

VueJs计算属性和侦听器 计算属性缓存 vs 方法 计算属性的 setter 侦听器

By 钱伯斯 on JavaScript Time 2019-12-04 from:互联网 789人已围观
简介:    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

<div id="app">
    <p>{{ message.split('').reverse().join('') }}</p>
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用计算属性。

基础例子

Html

<div id="app">
	<p>Original message: "{{ message }}"</p>
	<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

JavaScript

<script>
	var vm = new Vue({
	  el: '#app',
	  data: {
		message: 'Hello'
	  },
	  computed: {
		// 计算属性的 getter
		reversedMessage: function () {
		  // `this` 指向 vm 实例
		  return this.message.split('').reverse().join('')
		}
	  }
	})
</script>

结果:
Original message: "Hello"
Computed reversed message: "olleH"
这里我们声明了一个计算属性 reversedMessage。我们提供的函数将用作属性 vm.reversedMessage 的 getter 函数:
console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'
你可以打开浏览器的控制台,自行修改例子中的 vm。vm.reversedMessage 的值始终取决于 vm.message 的值。
你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

Example

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="vue.js"></script>
	</head>
	<body>
		//计算属性
		//基础例子
		<div id="app">
			<p>{{ message.split('').reverse().join('') }}</p>			
			<p>Original message: "{{ message }}"</p>
			<p>Computed reversed message: "{{ reversedMessage }}"</p>
			//计算属性缓存 vs 方法
			<p>Reversed message: "{{ reversedMessage() }}"</p>
			<p>{{ now }}</p>
		</div>		
		<script>
			var vm = new Vue({
				el: '#app',
				data: {
					message: 'Hello',
				},
				computed: {
					// 计算属性的 getter
					reversedMessage: function () {
					  // `this` 指向 vm 实例
					  return this.message.split('').reverse().join('')
					},
					now: function () {
						return Date.now()
					}
				},
				// 在组件中
				methods: {
					reversedMessage: function () {
						return this.message.split('').reverse().join('')
					}
				}			  
			});
			console.log(vm.reversedMessage) // => 'olleH'
			vm.message = 'Goodbye'
			console.log(vm.reversedMessage) // => 'eybdooG'
		</script>
		计算属性 vs 侦听属性
		<div id="app-1">{{ fullName }}</div>
		<script>
			var vm1 = new Vue({
				el: '#app-1',
				data: {
					firstName: 'Foo',
					lastName: 'Bar',
					fullName: 'Foo Bar'
				},
				watch: {
					firstName: function (val) {
					this.fullName = val + ' ' + this.lastName
				},
				lastName: function (val) {
					this.fullName = this.firstName + ' ' + val
				}
			  }
			});		
		</script>
		<div id="app-2">{{ fullName }}</div>
		<script>
			var vm2 = new Vue({
				el: '#app-2',
				data: {
					firstName: 'Foo',
					lastName: 'Bar'
				},
				computed: {
					fullName: function () {
						return this.firstName + ' ' + this.lastName
					}
				}
			})
		</script>
		//计算属性的 setter
		<div id="app-3">{{ fullName }}</div>
		<script>
			var vm3 = new Vue({
				el: '#app-3',
				data: {
					firstName: 'Foo',
					lastName: 'Bar'
				},
				computed: {
					fullName: {
						// getter
						get: function () {
							return this.firstName + ' ' + this.lastName
						},
						//setter
						set: function (newValue) {
							var names = newValue.split(' ')
							this.firstName = names[0]
							this.lastName = names[names.length - 1]
						}
					}
				}
			});
			vm3.fullName = 'John Doe'
		</script>
		//侦听器
		<div id="watch-example">
			<p>Ask a yes/no question:<input v-model="question"></p>
			<p>{{ answer }}</p>
		</div>	
		<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
		<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
		<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
		<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
		<script>
		var watchExampleVM = new Vue({
			el: '#watch-example',
			data: {
				question: '',
				answer: 'I cannot give you an answer until you ask a question!'
			},
			watch: {
				// 如果 `question` 发生改变,这个函数就会运行
				question: function (newQuestion, oldQuestion) {
					this.answer = 'Waiting for you to stop typing...'
					this.debouncedGetAnswer()
				}
			},
			created: function () {
				// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
				// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
				// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
				// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
				// 请参考:https://lodash.com/docs#debounce
				this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
			},
			methods: {
				getAnswer: function () {
					if (this.question.indexOf('?') === -1) {
						this.answer = 'Questions usually contain a question mark. ;-)'
						return
					}
					this.answer = 'Thinking...'
					var vm = this
					axios.get('https://yesno.wtf/api')
					.then(function (response) {
						vm.answer = _.capitalize(response.data.answer)
					})
					.catch(function (error) {
						vm.answer = 'Error! Could not reach the API. ' + error
					})
				}
			}
		})
		</script>				
	</body>
</html>
相关文章
文章评论

( 0 )