vue.js基础(4)

计算属性和侦听器

计算属性

<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方法

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

Reversed message:"{{reversedMessage()}}"

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

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

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

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

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

计算属性VS监听属性

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

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

"demo">{{fullName}}
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>


<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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。



<html>
    <head>
        <meta charset="utf-8" />
        <title>title>
    head>
    <body>
        <div id="app1">
            
            {{ 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/[email protected]/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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('
');
// 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>

你可能感兴趣的:(前端学习)