hehongwei44 / my-blog

我的博客
MIT License
137 stars 12 forks source link

Knockout js 之 pureComputed和computed的区别 #134

Open hehongwei44 opened 8 years ago

hehongwei44 commented 8 years ago

首先先看下knockout官网上是怎么解释这个的

computed: these are functions that are dependent on one or more other observables, and will automatically update whenever any of these dependencies change.

通俗的讲就是这个(被)观察对象依赖于一个或者多个其他的(被)观察对象,并且当其中任意一个(被)观察对象发生改变后都会自动进行更新。这个操作是在viewmodel绑定到knockout后就会发生。

pureComputed: computed observables, introduced in Knockout 3.2.0, provide performance and memory benefits over regular computed observables for most applications. This is because a computed observable doesn’t maintain subscriptions to its dependencies when it has no subscribers itself. This feature:

1.Prevents memory leaks from computed observables that are no longer referenced in an application but whose dependencies still exist.

2.Reduces computation overhead by not re-calculating computed observables whose value isn’t being observed.

什么意思呢?也就是pureComputed在之前的computed的基础上作了一些改进。首先就是防止内存泄露,其次是减少没有必要的计算的开销

为什么这么说呢。依旧看文档

Whenever it has no change subscribers, it is sleeping. When entering the sleeping state, it disposes all subscriptions to its dependencies. During this state, it will not subscribe to any observables accessed in the evaluator function (although it does keep track of them). If the computed observable’s value is read while it is sleeping, it is automatically re-evaluated if any of its dependencies have changed.

Whenever it has any change subscribers, it is awake and listening. When entering the listening state, it immediately subscribes to any dependencies. In this state, it operates just like a regular computed observable, as described in how dependency tracking works.

也就是这里会有两种模式,即休眠和监听模式,在休眠模式中,只有被绑定的元素被读到才会去处理所有的依赖和重新计算内容。而在监听模式中只要被观察的对象有更新,那么就会进行处理。

可以通过下面这个简单的例子体会下

<!DOCTYPE html>
<html>
<head> 
    <title>Data Binding with KnockoutJS</title>
</head>
<body> 

    <script type='text/javascript' src='js/knockout-3.2.0.js'></script> 
    <script> 
        function ViewModel() { 
            var self = this; 

            self.firstName = ko.observable('Steve'); 
            self.lastName = ko.observable('Kennedy'); 

            self.pureComputedExecutions = 0; 
            self.computedExecutions = 0; 

            self.pureComputedFullName = ko.pureComputed(function() { 
                // This is not recommended 
                self.pureComputedExecutions++; 
                return 'Hello ' + self.firstName() + ' ' + self.lastName(); 
            }); 

            self.computedFullName = ko.computed(function() { 
                self.computedExecutions++; 
                return 'Hello ' + self.firstName() + ' ' + self.lastName(); 
            }); 
        }; 

        var viewModel = new ViewModel(); 
        ko.applyBindings(viewModel); 

        alert('Pure computed executions: ' + viewModel.pureComputedExecutions); 
        alert('Computed executions: ' + viewModel.computedExecutions); 
    </script>
</body>
</html>

When this code is run, two alert messages are displayed that show the number of times the pureComputed and computed functions are called. Since pureComputed is in sleeping mode then the function has never been accessed, and the counter wil display 0. In contrast to this, the computed function is automatically evaluated on data binding, causing the counter to increase the number and display 1.

当上面的示例运行时,会弹出两个警告信息来展示pureComputedcomputed函数的调用情况,由于pureComputed当函数没有被调用的情况下处于休眠模式,所以调用的number值为0,和computed函数对比,它是在数据绑定前自动处理,处于监听模式。那么问题来了,怎样调用pureComputed函数呢?可以为下面两种情况:

<!DOCTYPE html>
<html>
<head>
    <title>Data Binding with KnockoutJS</title>
    <script type="text/javascript" src="lib/knockout-3.4.0.debug.js"></script>
</head>
<body>
<!--情况一: 通过data-bind指令调用-->
<span data-bind="text: pureComputedFullName"></span>
<script>
    function ViewModel() {
        var self = this;

        self.firstName = ko.observable('Steve');
        self.lastName = ko.observable('Kennedy');

        self.pureComputedExecutions = 0;
        self.computedExecutions = 0;

        self.pureComputedFullName = ko.pureComputed(function () {
            console.log("invoked...");
            // This is not recommended
            self.pureComputedExecutions++;
            return 'Hello ' + self.firstName() + ' ' + self.lastName();
        });

        self.computedFullName = ko.computed(function () {
            self.computedExecutions++;
            return 'Hello ' + self.firstName() + ' ' + self.lastName();
        });
    }

    var viewModel = new ViewModel();
    //情况而:直接通过VM对象调用
    viewModel.pureComputedFullName();
    ko.applyBindings(viewModel);

    alert('Pure computed executions: ' + viewModel.pureComputedExecutions);
    alert('Computed executions: ' + viewModel.computedExecutions);
</script>
</body>
</html>

帮助链接:http://stackoverflow.com/questions/30316954/knockoutjs-computed-vs-purecomputed

yanhuiyi commented 7 years ago

谢谢@hehongwei44,看了你的分享对pureComputed和Computed清楚多了。