zoukankan      html  css  js  c++  java
  • 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]

    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/

  • 相关阅读:
    [记录]Python2.7使用argparse模块
    [记录]MySQL读写分离(Atlas和MySQL-proxy)
    [记录]Shell中的getopts和getopt用法
    [记录]CentOS搭建SVN服务器(主从同步)
    [记录]Zabbix3.4配置监控Oracle12c的存活状态和表空间使用率
    [记录]一则清理MySQL大表以释放磁盘空间的案例
    [原创]Oracle 12c的备份和恢复策略
    Linux awk用法
    Oracle数据库学习笔记
    oracle无法删除当前连接用户方法
  • 原文地址:https://www.cnblogs.com/lightsong/p/10505047.html
Copyright © 2011-2022 走看看