在敲除组件中丢失上下文
Losing context in knockout component
我按照这个例子使用 requirejs 将组件打包为单个 AMD 模块:https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part2
问题是当它在视图模型中调用该函数时添加点击事件时,自身 属性 不包含视图模型并将其指向 window。是什么导致了这个问题?顺便说一句,如果它们在没有 requirejs 的情况下加载并且它们是内联的,则不会发生此问题。
Index.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dipping your feet into KnockoutJS Components</title>
<link href="Content/bootstrap.css" rel="stylesheet" />
<link href="Content/bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">KO Components</a>
</div>
</div>
</div>
<div class="container body-content" style="padding-top:50px">
<h2>Dipping your feet into KnockoutJS Components</h2>
<hr />
<greeter params='name: " Sumit!"'></greeter>
<greeter params='name: " Optimus!"'></greeter>
<greeter params='name: " Bumblebee!"'></greeter>
</div>
<footer class="navbar navbar-fixed-bottom">
<div class="container-fluid">
<p> © 2014 - Still Learning</p>
</div>
</footer>
<script src="App/boot/require.config.js"></script>
<script data-main="App/boot/startup" src="Scripts/require/require.js"></script>
</body>
</html>
require.config.js
var require = {
baseUrl: "/",
paths: {
"bootstrap": "Scripts/bootstrap/bootstrap",
"jquery": "Scripts/jquery/jquery-1.9.0",
"knockout": "Scripts/knockout/knockout-3.2.0beta.debug",
"text": "Scripts/require/text"
},
shim: {
"bootstrap": {
deps: ["jquery"]
}
}
}
startup.js
define(['jquery', 'knockout', 'bootstrap'], 函数 ($, ko) {
ko.components.register('greeter', { require: 'App/components/greeter/greeting' });
ko.applyBindings();
});
greeting.html - 组件模板
<div class='container-fluid'>
<div> Hello <span data-bind='text: greeting'></span></div>
<div> It is <span data-bind='text: date'></span></div>
<input type="button" value="test" data-bind="click: testClick" />
</div>
greeting.js - 组件视图模型
define(["knockout", "text!./greeting.html"], function (ko, greeterTemplate) {
function greeterViewModel(params) {
var self = this;
self.greeting = ko.observable(params.name);
self.date = ko.observable(new Date());
self.testClick = function () {
//self is pointing to window instead of greeterViewModel
debugger;
};
}
return { viewModel: greeterViewModel, template: greeterTemplate };
});
JavaScript 编译器试图在闭包方面变得聪明。因为您的函数不使用闭包中的任何变量,所以该函数根本不包含闭包。将您的代码更改为此,您将看到它有效:
self.testClick = function () {
console.log(self);
debugger;
};
我按照这个例子使用 requirejs 将组件打包为单个 AMD 模块:https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part2
问题是当它在视图模型中调用该函数时添加点击事件时,自身 属性 不包含视图模型并将其指向 window。是什么导致了这个问题?顺便说一句,如果它们在没有 requirejs 的情况下加载并且它们是内联的,则不会发生此问题。
Index.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dipping your feet into KnockoutJS Components</title>
<link href="Content/bootstrap.css" rel="stylesheet" />
<link href="Content/bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">KO Components</a>
</div>
</div>
</div>
<div class="container body-content" style="padding-top:50px">
<h2>Dipping your feet into KnockoutJS Components</h2>
<hr />
<greeter params='name: " Sumit!"'></greeter>
<greeter params='name: " Optimus!"'></greeter>
<greeter params='name: " Bumblebee!"'></greeter>
</div>
<footer class="navbar navbar-fixed-bottom">
<div class="container-fluid">
<p> © 2014 - Still Learning</p>
</div>
</footer>
<script src="App/boot/require.config.js"></script>
<script data-main="App/boot/startup" src="Scripts/require/require.js"></script>
</body>
</html>
require.config.js
var require = {
baseUrl: "/",
paths: {
"bootstrap": "Scripts/bootstrap/bootstrap",
"jquery": "Scripts/jquery/jquery-1.9.0",
"knockout": "Scripts/knockout/knockout-3.2.0beta.debug",
"text": "Scripts/require/text"
},
shim: {
"bootstrap": {
deps: ["jquery"]
}
}
}
startup.js
define(['jquery', 'knockout', 'bootstrap'], 函数 ($, ko) {
ko.components.register('greeter', { require: 'App/components/greeter/greeting' });
ko.applyBindings();
});
greeting.html - 组件模板
<div class='container-fluid'>
<div> Hello <span data-bind='text: greeting'></span></div>
<div> It is <span data-bind='text: date'></span></div>
<input type="button" value="test" data-bind="click: testClick" />
</div>
greeting.js - 组件视图模型
define(["knockout", "text!./greeting.html"], function (ko, greeterTemplate) {
function greeterViewModel(params) {
var self = this;
self.greeting = ko.observable(params.name);
self.date = ko.observable(new Date());
self.testClick = function () {
//self is pointing to window instead of greeterViewModel
debugger;
};
}
return { viewModel: greeterViewModel, template: greeterTemplate };
});
JavaScript 编译器试图在闭包方面变得聪明。因为您的函数不使用闭包中的任何变量,所以该函数根本不包含闭包。将您的代码更改为此,您将看到它有效:
self.testClick = function () {
console.log(self);
debugger;
};