knockoutjs 主页面调用组件
Calling component on main page in knockoutjs
我在使用 knockoutjs 组件时遇到了一些问题,我正在按照 official knockout component documentation 中的示例进行操作。
如何在主页上调用我的小部件组件?我想我可能把代码放在了错误的地方。
代码:
index.html
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/libs/knockout/knockout-3.3.0.js" ></script>
<script type="text/javascript" src="js/widget.js" ></script>
</head>
<body>
<div>TODO write content</div>
</body>
</html>
main.js
ko.components.register('like-or-dislike', {
viewModel: { require: 'files/widget' },
template: { require: 'text!files/widget.html' }
});
alert(ko.components.isRegistered('like-or-dislike'));
widget.html
<ul data-bind="foreach: products">
<li class="product">
<strong data-bind="text: name"></strong>
<like-widget params="value: userRating"></like-widget>
</li>
</ul>
widget.js
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = [
new Product('Garlic bread'),
new Product('Pain au chocolat'),
new Product('Seagull spaghetti', 'like') // This one was already 'liked'
];
}
ko.applyBindings(new MyViewModel());
documentation explains how to load components from external files using requirejs 的时候好像有点迷路了。
I think I may be putting the code in the wrong places
是的,您确实放错了一些代码。让我们让您重回正轨:)
首先,你的widget.js中的代码属于你的main.js 以及对 ko.components.register
的调用。
其次,您在 widget.html 中的标记,对于您的视图模型,属于 index.html。
第三,您似乎缺少小部件本身的代码和标记。
看看下面的工作示例。我已经把每段代码属于哪个文件放在代码上方的注释中。
您将不需要通过将它们作为第一个参数传递给requirejsdefine
来定义模块名称像我一样的功能:
define("files/widget",...
define("main",...
这只适用于 Stack Snippet. requirejs uses a convention based on file paths if the module name is not supplied, for example requirejs will look for a file called widget.js in a folder called files when given the module name files/widget
. Please read the requirejs docs。
// This goes in widget.html, only the html.
// This example uses the define function only to work in this snippet.
define("text!files/widget.html", [], function() {
return '<div class="like-or-dislike" data-bind="visible: !chosenValue()">\
<button data-bind="click: like">Like it</button>\
<button data-bind="click: dislike">Dislike it</button>\
</div>\
<div class="result" data-bind="visible: chosenValue">\
You <strong data-bind="text: chosenValue"></strong> it\
</div>'
});
// This goes in in widget.js, you must use the define function.
define("files/widget", [], function() {
return function(params) {
// Data: value is either null, 'like', or 'dislike'
this.chosenValue = params.value;
// Behaviors
this.like = function() {
this.chosenValue('like');
}.bind(this);
this.dislike = function() {
this.chosenValue('dislike');
}.bind(this);
}
});
// all of the below goes into main.js
require.config({
paths: {
"knockout": "http://knockoutjs.com/downloads/knockout-3.3.0",
"text": "https://rawgit.com/requirejs/text/master/text"
}
});
define("main", ["knockout"], function(ko) {
ko.components.register('like-or-dislike', {
viewModel: {
require: 'files/widget'
},
template: {
require: 'text!files/widget.html'
}
});
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = [
new Product('Garlic bread'),
new Product('Pain au chocolat'),
new Product('Seagull spaghetti', 'like') // This one was already 'liked'
];
}
ko.applyBindings(new MyViewModel());
})
<!-- this goes in the body of index.html -->
<ul data-bind="foreach: products">
<li class="product">
<strong data-bind="text: name"></strong>
<like-or-dislike params="value: userRating"></like-or-dislike>
</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.19/require.min.js" data-main="main"></script>
我在使用 knockoutjs 组件时遇到了一些问题,我正在按照 official knockout component documentation 中的示例进行操作。
如何在主页上调用我的小部件组件?我想我可能把代码放在了错误的地方。
代码: index.html
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/libs/knockout/knockout-3.3.0.js" ></script>
<script type="text/javascript" src="js/widget.js" ></script>
</head>
<body>
<div>TODO write content</div>
</body>
</html>
main.js
ko.components.register('like-or-dislike', {
viewModel: { require: 'files/widget' },
template: { require: 'text!files/widget.html' }
});
alert(ko.components.isRegistered('like-or-dislike'));
widget.html
<ul data-bind="foreach: products">
<li class="product">
<strong data-bind="text: name"></strong>
<like-widget params="value: userRating"></like-widget>
</li>
</ul>
widget.js
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = [
new Product('Garlic bread'),
new Product('Pain au chocolat'),
new Product('Seagull spaghetti', 'like') // This one was already 'liked'
];
}
ko.applyBindings(new MyViewModel());
documentation explains how to load components from external files using requirejs 的时候好像有点迷路了。
I think I may be putting the code in the wrong places
是的,您确实放错了一些代码。让我们让您重回正轨:)
首先,你的widget.js中的代码属于你的main.js 以及对 ko.components.register
的调用。
其次,您在 widget.html 中的标记,对于您的视图模型,属于 index.html。
第三,您似乎缺少小部件本身的代码和标记。
看看下面的工作示例。我已经把每段代码属于哪个文件放在代码上方的注释中。
您将不需要通过将它们作为第一个参数传递给requirejsdefine
来定义模块名称像我一样的功能:
define("files/widget",...
define("main",...
这只适用于 Stack Snippet. requirejs uses a convention based on file paths if the module name is not supplied, for example requirejs will look for a file called widget.js in a folder called files when given the module name files/widget
. Please read the requirejs docs。
// This goes in widget.html, only the html.
// This example uses the define function only to work in this snippet.
define("text!files/widget.html", [], function() {
return '<div class="like-or-dislike" data-bind="visible: !chosenValue()">\
<button data-bind="click: like">Like it</button>\
<button data-bind="click: dislike">Dislike it</button>\
</div>\
<div class="result" data-bind="visible: chosenValue">\
You <strong data-bind="text: chosenValue"></strong> it\
</div>'
});
// This goes in in widget.js, you must use the define function.
define("files/widget", [], function() {
return function(params) {
// Data: value is either null, 'like', or 'dislike'
this.chosenValue = params.value;
// Behaviors
this.like = function() {
this.chosenValue('like');
}.bind(this);
this.dislike = function() {
this.chosenValue('dislike');
}.bind(this);
}
});
// all of the below goes into main.js
require.config({
paths: {
"knockout": "http://knockoutjs.com/downloads/knockout-3.3.0",
"text": "https://rawgit.com/requirejs/text/master/text"
}
});
define("main", ["knockout"], function(ko) {
ko.components.register('like-or-dislike', {
viewModel: {
require: 'files/widget'
},
template: {
require: 'text!files/widget.html'
}
});
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = [
new Product('Garlic bread'),
new Product('Pain au chocolat'),
new Product('Seagull spaghetti', 'like') // This one was already 'liked'
];
}
ko.applyBindings(new MyViewModel());
})
<!-- this goes in the body of index.html -->
<ul data-bind="foreach: products">
<li class="product">
<strong data-bind="text: name"></strong>
<like-or-dislike params="value: userRating"></like-or-dislike>
</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.19/require.min.js" data-main="main"></script>