MarginLon MarginLon
首页
  • Web

    • Web基础
    • Web布局
    • CodeSnippet
  • Vue

    • Vue
  • React

    • React
  • Node.js

    • Node.js
  • 技术文档
  • UI组件库
  • 动画库
  • 图形库
  • 桌面端
  • 学习笔记
  • 生活笔记
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

MarginLon

http://info.cern.ch
首页
  • Web

    • Web基础
    • Web布局
    • CodeSnippet
  • Vue

    • Vue
  • React

    • React
  • Node.js

    • Node.js
  • 技术文档
  • UI组件库
  • 动画库
  • 图形库
  • 桌面端
  • 学习笔记
  • 生活笔记
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

  • UI组件库

  • 动画库

  • 图形库

  • 桌面端

  • Web3D

  • 框架篇

    • KnockoutJS
      • 声明
      • 监控 observable
      • 显示订阅 subscribe
      • 监控数组 observableArray
      • 计算监控 computed
      • 绑定
        • 1. 文本与外观
        • 2. 流程控制
        • 3. 表单
        • 4. 模板渲染
        • 5. 绑定语法
        • 6. 自定义绑定
      • Reference
  • 技术
  • 框架篇
MarginLon
2023-11-12
目录

KnockoutJS

# 声明

let viewModel = {}
ko.applyBindings(viewModel, document.getElementById('app'))
1
2

# 监控 observable

var viewModel = {
    firstName: ko.observable('Margin'),
}
1
2
3

# 显示订阅 subscribe

// 一般不需要手动订阅,除数据变化需要自定义逻辑时
let sub = vm.variable.subscribe(function (newValue) {
    // 自定义逻辑
})

sub.dispose() // 取消订阅 
1
2
3
4
5
6

# 监控数组 observableArray

ko.observableArray(ary)

ko.isObservableArray(val)
/* 

所有这些函数都是和JavaScript数组原生函数等价的,唯一不同的数组改变可以通知订阅者:

    myObservableArray.push('Some new value') 在数组末尾添加一个新项

    myObservableArray.pop() 删除数组最后一个项并返回该项

    myObservableArray.unshift('Some new value') 在数组头部添加一个项

    myObservableArray.shift() 删除数组头部第一项并返回该项

    myObservableArray.reverse() 翻转整个数组的顺序

    myObservableArray.sort() 给数组排序

    myObservableArray.remove(someItem) 删除所有等于someItem的元素并将被删除元素作为一个数组返回

    myObservableArray.remove(function(item) { return item.age < 18 }) 删除所有age属性小于18的元素并将被删除元素作为一个数组返回

    myObservableArray.removeAll(['Chad', 132, undefined]) 删除所有等于'Chad', 123, or undefined的元素并将被删除元素作为一个数组返回


*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 计算监控 computed

ko.computed(callback)

ko.computed({read, write, owner})

// 纯计算监控 防止内存泄漏和计算过载 类似js里的纯函数
ko.pureComputed(callback, this) 

ko.computed(callback, this, {pure: true})
1
2
3
4
5
6
7
8

# 绑定

# 1. 文本与外观

<!-- visible -->
<body>
    <div data-bind="visible: shouldShowMessage">
    </div>
    <div data-bind="visible: myArr().length > 0">
    </div>
    <script>
        let vm = {
            shouldShowMessage: ko.observable(true),
            myArr: ko.observableArray([1, 2, 3])
        }
        ko.applyBindings(vm)
    </script>
</body>

<!-- text -->
<!-- html -->

<!-- class -->
<!-- css -->
<!-- style -->
<body>
    <div data-bind="class: profitStatus">
    </div>
    <div data-bind="css: {
        profitWarning: currentProfit() < 0,
        majorHighlight: isSevere
    }">
    </div>
    <div data-bind="class: profitStatus, css: {
        profitWarning: currentProfit() < 0,
        majorHighlight: isSevere
    }">
    </div>
    <!-- 一个变量控制多个类 -->
    <div data-bind="css: {
        'profitWarning majorHighlight large' : currentProfit() < 0,
    }">
    </div>
    <!-- 蛇形命名需要引号包裹 -->
    <div data-bind="css: {
        'btn-success': isSuccess,
    }">
    <script>
        let vm = {
        // ...    
        }
        ko.applyBindings(vm)
    </script>
</body>

<!-- attr -->
<body>
    <a data-bind="attr: {href: url, title: details, target: ways }">

    </a>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 2. 流程控制

<!-- foreach -->
<body>
    <table>
        <thead>
            <tr>
                <th>Index</th>
                <th>First Name</th>
                <th>Last Name</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: people">
            <tr>
                <td data-bind="text: $index"></td>
                <td data-bind="text: firstName"></td>
                <td data-bind="text: lastName"></td>    
            </tr>
            <tr>
                <td data-bind="text: '--'"></td>
                <td data-bind="text: $data.firstName"></td>
                <td data-bind="text: $data.lastName"></td>    
            </tr>
        </tbody>
    </table>
</body>
<script>
    let vm = {
        people: {
            {firstName: 'John', lastName: 'Doe'},
            {firstName: 'John', lastName: 'Doe'},
            {firstName: 'John', lastName: 'Doe'}
        }
    }
</script>

<body>
    <ul>
        <li>
            Name at position <span data-bind="text: $index"></span> :
            <span data-bind="text: name"></span>
            <a href="#" data-bind="click: $parent.removePerson"> Remove </a>
        </li>
    </ul>
    <button data-bind="click: addPerson"> Add </button>
    <script>
        function AppViewModel() {
            var self = this
            self.people = ko.observableArray([
                {name: 'John Doe'},
                {name: 'Jane Doe'},
                {name: 'John Smith'}
            ])
            self.addPerson = function() {
                self.people.push({name: 'Unknown'})
            }
            self.removePerson = function() {
                self.people.remove(this)
            }
        }
        ko.applyBindings(new AppViewModel())
    </script>
</body>

<!-- if & ifNot -->

<body>
    <ul data-bind="foreach: people">
        <li>
            姓名:<b data-bind="text: name"></b>
        <div data-bind="if: age">
            年龄:<b data-bind="text: age"></b>
        </div>

        <div data-bind="ifnot: age">
            年龄:<b> -- </b>
        </div>

        <!-- ko ifnot age -->
        年龄: <b> -- </b>
        <!-- /ko-->
        </li>
    </ul>

    <script>
        var vm = {
            showMessage: ko.observable(false),
            people:[
                { name: 'A', age: null},
                { name: 'B', age: 20}
            ]
        }
    </script>
</body>

<!-- 绑定上下文  with & using / let -->

<body>
    <h1 data-bind="text: city"></h1>
    <p>
        Latitude:<span data-bind="text: coords.latitude"></span>
        Longitude:<span data-bind="text: coords.longitude"></span>
    </p>

    <p data-bind="with: coords">
        Latitude:<span data-bind="text: latitude"></span>
        Longitude:<span data-bind="text: longitude"></span>
    </p>

    <p data-bind="using: coords">
        Latitude:<span data-bind="text: latitude"></span>
        Longitude:<span data-bind="text: longitude"></span>
    </p>
    <script>
        var vm = {
            city: 'London',
            coord: {
                latitude: 51.5001524,
                longitude: -0.1262362
            }
        }
    </script>
</body>

<body>
    <!-- ko let: {
        inventory: {suppliers: suppliers, bins: bins},
        calculateDisplay: someCalculation
    } -->
    <div data-bind="foreach: {data: inventory.suppliers, as: 'supplier'}">
        <div data-bind="foreach: {data: inventory.bins, as: 'bin'}">
            <span data-bind="text: calculatedDisplay(supplier, bin)"></span>
        </div>
    </div>
    <!-- /ko -->
    <script>
        var vm = {
            suppliers: [1, 2, 3],
            bins: ['a', 'b', 'c'],
            someCalculation: function (supplier, bin) {
                return supplier + bin;
            }
        }
    </script>
</body>

<!-- component -->
<body>
    <div data-bind="component: 'message-editor'"></div>
    <!-- <message-editor></message-editor> -->
    <div data-bind="component: {
        name: 'message-editor',
        params: {initialText: 'Hello World!'
    }"></div>
    <!-- <message-editor params="initialText:'Hello World!'"></message-editor> -->
    <script>
        ko.components.register('message-editor', {
            viewModel: function(params) {
                this.text = ko.observable(params && params.initialText || '')
            }, 
            template: '消息: <input data-bind="value: text" />' 
                    + '(length: <span data-bind="text: text().length"></span>'
            })
    </script>
</body>

<body>
    <template id="my-special-list-template">
        <h3>模板头部</h3>
        <ul data-bind="foreach: {data: myItems, as: 'myItem'}">
            <li>
                <h4>模板列表头部</h4>
                <!-- $componentTemplateNodes 表示自定义元素的模板节点 -->
                <!-- ko template: { nodes: $componentTemplateNodes, data: myItem 
                    } -->
                <!-- /ko -->
            </li>
        </ul>
    </template>

    <my-special-list params="items: peopleArray">
        <em data-bind = 'text: name'></em>
        <em data-bind = 'text: age'></em>
    </my-special-list>
    <script>
        ko.components.register('my-special-list', {
            template: {
                element: 'my-special-list-template'
            },
            viewModel: function(params){
                this.myItems = params.items
            }
        })
        ko.applyBindings({
            peopleArray: ko.observableArray([
                { name: 'Lewis', age: 56},
                { name: 'Lewis', age: 56}
            ])
        })
    </script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

# 3. 表单

<!-- click -->
<body>
    <!-- 注意阻止默认事件 事件冒泡 -->
    <div>
        <span data-bind="text: number"></span>
        <button data-bind ="click: increment"> + </button>
        <a href="https://www.baidu.com" data-bind="click: increment"></a>
    </div>
    <div data-bind="click: f1" class="d1">
        <div data-bind="click: f2" class="d2">
            <button data-bind="click: f3, clickBubble: false">Click me</button>
        </div>
    </div>
    <script>
        var vm = {
            number: ko.observable(0),
            increment: function(){
                var previousCount = this.number()
                this.number(previousCount + 1)
                // return true // 返回 true 会执行跳转,不返回,只执行累加
            },

            f1 : function () {
                alert('1')
            },
            f2 : function () {
                alert('2')
            },
            f3 : function () {
                alert('3')
            }
        }
    </script>
</body>

<body>
    <button data-bind="click: myFunction">
        Click me
    </button>
    <button data-bind="click: function(data, event) {
        myFunction('param1','param2',data, event)
    }">
        Click me
    </button>
    <button data-bind="click: myFunction.bind($data, 'param1', 'param2', event)">
        Click me
    </button>
    <script>
        var vm = {
            my Function: function(data, event) {
                console.log(data, event)
                if(event.shiftKey) {
                    alert('shiftKey')
                } else {
                    alert('click')
                }
            }
        }
    </script>
</body>

<!-- event -->
<div>
     <div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails
     }"></div>
     <div data-bind="visible: detailsEnabled"></div>
</div>

<body>
    <ul data-bind="foreach: places">
        <!-- 显示内容$data, 绑定事件event -->
        <li data-bind="text: $data, event:{
            mouseover: $parent.logMouseOver
        }"></li>
    </ul>
    <p><span data-bind="text: lastInterest"></span></p>
    <script>
        var self = this;
        self.lastInterest = ko.observable();
        self.places = ko.observableArray(['London', 'Paris', 'Rome']);

        self.logMouseOver = function(place) {
            self.lastInterest(place);
        }
    </script>
</body>

<!-- submit -->
<body>
    <form data-bind="submit: doSomething">
        <input type="text" name="username" placeholder="请输入用户名" 
        data-bind="value: username"/>
        <input type="password" name="password" placeholder="请输入密码"
        data-bind="value: password"/>
        <button type="submit">Submit</button>
    </form>
    <script>
        var vm = {
            username: ko.observable(),
            password: ko.observable(),
            doSomething: function(formElement) {
                // if($(formElement).valid()) { }
                console.log(formElement)
                console.log(this.username())
                console.log(this.password())
            }
        }
        ko.applyBindings(vm)
    </script>
</body>

<!-- enable & disable -->
<!-- 控制 input  select  textarea -->


<!-- value & textInput -->
<!-- value绑定change事件  textInput 绑定onInput事件-->

<body>
    
    <select data-bind="options: countries,
    OptionsCaption: '选国家',
    value: selectedCountry,
    valueAllowUnset: true"></select>
    
</body>

<!-- hasFocus -->
<!-- checked -->
<!-- options -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

# 4. 模板渲染

# 5. 绑定语法

# 6. 自定义绑定

# Reference

汤姆大叔的博客 (opens new window)
博客园 SmallProgram (opens new window)
bilibili (opens new window)
bilibili (opens new window)

编辑 (opens new window)
上次更新: 2023/12/25, 17:18:00
ThreeJS

← ThreeJS

最近更新
01
综述
10-17
02
前言
10-12
03
let和const
10-12
更多文章>
Theme by Vdoing | Copyright © 2019-2024 MarginLon | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式