您的位置:首页 > 产品设计 > UI/UE

vue.js基础(4)

2018-03-29 08:39 344 查看

计算属性和侦听器

计算属性

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


在这里,模版不再是简单的声明式逻辑

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

例:

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


var vm = new Vue({
el:"#example",
data:{
message:"Hello"
},
computed:{
//计算属性的getter
reverseMessage:function(){
//'this'指向VM实例
return this.message.split('').reverse.join('')
}
}
});


这里我们声明了一个计算属性 ++reversedMessage++。我们提供的函数将作用属性++vm.reversedMessage++的++getter++函数

console.log(vm.reverseMessage) //=>"olleH"
vm.message = "Goodbye"
console.log(vm.reversedMessage) //=>"eybdoG"


注:vm.reversedMessage的值始终取决于vm.message

计算属性缓存VS方法

可以通过在表达式中调用方法来达到同样的效果:

<p>Reversed message:"{{reversedMessage()}}"</p>

//在组件中
methods:{
reversedMessage:function(){
return this.message.split('').reverse().join('')
}
}


可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

例:下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

computed:{
now:function(){
return Date.now()
}
}


每当触发重新渲染时,调用方法将总会再次执行函数。

计算属性VS监听属性

侦听属性:来观察和响应 Vue 实例上的数据变动。

当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。

<div id="demo">{{fullName}}</div>

var vm = new Vue({
el:'#demo';
data:{
firstName:'Foo',
lastName:'Bar',
fullName:'Foo Bar'
},
watch:{
firstName:function(val){
this.fullName = val + ' ' + this.lastName
},
lastName:function(val){
this.fullName = this.flrstName  + ' ' +  val
},
}
});


将它与计算属性的版本进行比较:

var vm = new Vue({
el:'#demo',
data:{
firstName:'foo',
lastName:'Bar'
},
computed:{
fullName:function(){
return this.firstName + ' ' + this.lastName
}
}
});


现在再运行vm.fullName = “John Doe” 时,setter会被调用,vm.firstName和vm.lastName也会相应的被更新

侦听器

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

例:

<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:'123abc'
},
watch:{
//如果 `question` 发生改变,这个函数就运行
question:function(newQuestion,oldQuestion){
this.answer = "456efg",
this.getAnswer()
}
},
methods:{
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
getAnswer: _.debounce(
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
})
},
// 这是我们为判定用户停止输入等待的毫秒数
500
)
}
});
</script>


结果:

Ask a yes/no question:

I cannot give you an answer until you ask a question!

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app1">
<!--reverse() 方法用于颠倒数组中元素的顺序。
split() 方法用于把一个字符串分割成字符串数组。-->
{{ message.split('').reverse().join("") }}
</div>
<div id="app2">
<p>原始字符串:{{message}}</p>
<p>计算后反转字符串:{{reversedMessage}}</p>
</div>
<div id="app3">
<p>原始字符串 :{{message}}</p>
<p>计算后反转字符串:{{reversedMessage}}</p>
<p>使用方法后反转字符串:{{reversedMessage2()}}</p>
</div>
<div id="app4">
<p>{{site}}</p>
</div>
<div id="computed_props">
千米:<input type="text" v-model="kilometers">
米:<input type="text" v-model="meters">
</div>
<p id="info"></p>

<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>

</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<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 type="text/javascript">
new Vue({
el:"#app1",
data:{
message:'Runoob!'
}
});
new Vue({
el:'#app2',
data:{
message:'Runoob!'
},
//计算属性
computed:{
//计算属性的getter
reversedMessage:function(){
//this指向Vm实例
return this.message.split('').reverse().join("")
}
}
});
new Vue({
el:'#app3',
data:{
message:'Runoob!'
},
computed:{
reversedMessage:function(){
return this.message.split("").reverse().join('')
}
},
methods:{
reversedMessage2:function(){
return this.message.split('').reverse().join('')
}
}
});
var vm = new Vue({
el:'#app4',
data:{
name:"Google",
url:"http://www.google.com"
},
computed:{
site:{
//getter
get:function(){
return this.name + " " + this.url
},
//setter
set:function(newValue){
var names = newValue.split(' ');
this.name = name[0];
this.url = names[names.length - 1]
}
}
}
});
//  //调用setter,vm.name 和vm.url 也会被对应更新
//  vm.site = '菜鸟教程 http://www.runoob.com'; //  document.write('name:' + vm.name);
//  document.write('<br>');
//  document.write('url:'+vm.url);

//  var vm = new Vue({
//      el:'#computed_props',
//      data:{
//          kilometers:0,
//          meters:0
//      },
//      methods:{},
//      computed:{},
//      watch:{
//          kilometers:function(val){
//              this.kilometers = val;
//              this.meters = val * 1000;
//          },
//          meters:function(val){
//              this.kilometers= val/ 1000;
//              this.meters = val;
//          }
//      }
//  });
//  //$watch是一个实例方法
//  vm.$watch('kilometers',function(newValue,oldValue){
//      //这个回调函数将在vm.kilometers改变后调用
//      document.getElementById('info').innerHTML = '修改前值为:' + oldValue +"修改后的值:" + newValue;
//  })

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.getAnswer()
}
},
methods: {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
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
})
},
// 这是我们为判定用户停止输入等待的毫秒数
500
)
}
})

</script>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: