Knockoutjs 响应式计算研究

reactive programming

https://en.wikipedia.org/wiki/Reactive_programming

In computing, reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. With this paradigm it is possible to express static (e.g., arrays) or dynamic (e.g., event emitters) data streams with ease, and also communicate that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the changed data flow.[citation needed]

 a := b + c {\displaystyle a:=b+c} a:=b+c would mean that a {\displaystyle a} a is being assigned the result of b + c {\displaystyle b+c} b+c in the instant the expression is evaluated, and later, the values of b {\displaystyle b} b and c {\displaystyle c} c can be changed with no effect on the value of a {\displaystyle a} a. On the other hand, in reactive programming, the value of a {\displaystyle a} a is automatically updated whenever the values of b {\displaystyle b} b or c {\displaystyle c} c change, without the program having to re-execute the statement a := b + c {\displaystyle a:=b+c} a:=b+c to determine the presently assigned value of a . {\displaystyle a.} a.[citation needed]

 

Reactive programming has been proposed as a way to simplify the creation of interactive user interfaces and near-real-time system animation.[citation needed]

For example, in a model–view–controller (MVC) architecture, reactive programming can facilitate changes in an underlying model that are reflected automatically in an associated view.[1]

 

knockoutjs reactive

https://knockoutjs.com/documentation/observables.html

第一,定义 基础的 可观察对象:

var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123)
};

第二, 定义存在依赖其他可观察对象的 计算对象

function AppViewModel() {
    // ... leave firstName and lastName unchanged ...
 
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
}

第三、绑定到视图

The name is <span data-bind="text: fullName"></span>

 

如果基础的 可观察对象 改变, 则视图会自动跟着改变。

 

实现原理

https://github.com/fanqingsong/knockout-prototype

 

knockout模块实现, 包括 observale 和 computed 接口实现, 以及内部依赖管理实现。

let ko = {}

ko.say = () => console.log("hello world")

ko.dependency = (() => {
    let callerstack = []
    let currentCaller

    return {
        currentCaller,
        callerstack
    }
})();


ko.observable = (initVal) => {
    // for record caller, ie observer
    let observerCache = [];

    // store current observable value
    let currentVal = "";
    if(initVal !== undefined){
        console.log("initVal 0=", initVal)
        currentVal = initVal;
    }

    let observable = (newVal) => {
        // for read, subscribe to caller
        if( newVal === undefined ) {
            if (ko.dependency.currentCaller) {
                observerCache.push(ko.dependency.currentCaller)
            }

            return currentVal;
        // for write
        } else {
            currentVal = newVal;

            console.log("===",observerCache.length)

            for (const index in observerCache) {
                console.log("-----------3-", observerCache[index]);
                observerCache[index].callEvalWithDeps();
            }
        }
    }

    return observable
}

ko.computed = (evalFunc) => {
    // store current observable value
    let currentVal = "";

    let unValuated = true;

    let computedObservable = () => {

        if (unValuated){
            computedObservable.callEvalWithDeps();
            unValuated = false;
        }

        return currentVal;
    }

    computedObservable.callEvalWithDeps = () => {
        if (ko.dependency.currentCaller) {
            ko.dependency.callerstack.push(ko.dependency.currentCaller)
        }

        ko.dependency.currentCaller = computedObservable;

        currentVal = evalFunc();

        let parent = ko.dependency.callerstack.pop();
        ko.dependency.currentCaller = parent;
    }

    return computedObservable
}

module.exports = ko

 

调用

import ko from "./knockout.js"
ko.say();

let aObservable = ko.observable("a");
console.log("aObservable=", aObservable());


let bComputed = ko.computed(() => {
  let result = aObservable() + "b";

  console.log("result=", result);

  return result;
})

// bind subscription to aObservable
let bVal = bComputed();
console.log("bVal=", bVal);

// trigger reactive effect
aObservable("c");

console.log("bComputed=", bComputed())

 

运行

 

 

参考:

https://knockoutjs.com/documentation/computed-dependency-tracking.html

https://www.reactivemanifesto.org/

 

转载于:https://www.cnblogs.com/lightsong/p/10505047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值