Component
Template
Use the tag to position the custom element’s source HTML.
使用标签获取自定义标签元素的源HTML内容.
can.Component.extend({
tag: "hello-world",
template: "<h1><content/></h1>"
});
Html Template
<hello-world>Hi There</hello-world>
Html
<hello-world><h1>Hi There</h1></hello-world>
Using html attributes like can-EVENT-METHOD, you can directly call a scope method from a template
使用html属性类似can-click=’back’方式,可以在template中访问定义在scope中的back方法.
Template中使用{{}}访问scope中的属性或方法.
Scope
If you want to set the string value of the attribute on scope, give scope a default value of “@”.
默认使用’@’符号获取自定义标签的属性值
can.Component.extend({
tag: "hello-world",
template: "<h1>{{message}}</h1>",
scope: {
message: "@"
}
});
var template = can.mustache("<hello-world message='Howdy'/>");
template({})
<hello-world><h1>Howdy</h1></hello-world>
Scope也可以是一个function,但不常用.定义:function(attrs, parentScope, element)
attrs:custom element’s attributes(自定义标签元素的属性)
parentScope:(待理解)
element:自定义标签元素.
Events
A component’s events object is used as the prototype of a can.Control.
Component的Events对象被用作can.Control的原型属性.
The component’s scope is available within event handlers as this.scope.
在Events对象中使用this.scope.来访问Component的scope属性.
The events object can also listen to objects or properties on the component’s scope
Events对象同样可以监听Componet的scope对象的属性.
E.g.:监听scope的offset的属性变化,作相应的处理
can.Component.extend({
tag: "my-paginate",
template: "Page <span>1</span> <button class='next'>Next</button>",
scope: {
offset: 0,
page: function() {}
},
events: {
"{scope} offset": function() {
this.element.find("span").text(this.scope.page())
}
}
});
在Components的Event中可以绑定inserted 和removed事件,用于监听Component的Tag在页面中的插入和删除
Tag
Tag请用小写定义,大写时有时会有问题
Control
Creating a control instance:new can.Control( element, options )
var todosControl = new Todos( '#todos', {} );
element: is the NodeList consisting of the element the control is created on
options :merged with the control’s static defaults property
Templated Event Handlers
Customize event handler behavior with “{NAME}” in the event handler name
自定义事件行为:在event定义中使用{Name}
var Todos = can.Control.extend({
init: function( element , options ) { ... },
'li click': function( li ) { ... },
'li .destroy {destroyEvent}': function( el, ev ) { ... }
});
// create Todos with this.options.destroyEvent
new Todos( '#todos', { destroyEvent: 'mouseenter' } );
Values inside {NAME} are looked up on the control’s this.options first, and then the window.
{Name}中的值首先在control的this.options中查找,之后是window
E.g.:所以上面的例子,我们让他从window中查找:
var Todos = can.Control.extend({
init: function( element , options ) { ... },
'li click': function( li ) { ... },
'li .destroy {Events.destroy}': function( el, ev ) { ... }
});
Events = { destroy: 'click' };
// Events.destroy is looked up on the window.
new Todos( '#todos' );
If the value inside {NAME} is an object, Control will bind to that object to listen for events.
如果{Name}中的值是一个Object,Control将对一个该对象bind监听对应事件
var Tooltip = can.Control.extend({
'{window} click': function( el, ev ) {
// hide only if we clicked outside the tooltip
if ( !this.element.has( ev.target ) ) {
this.element.remove();
}
}
});
Defaults
Default options provided for when a new control is created without values set in options
Default Options 在新建一个Control对象时提供属性的默认值.
Message = can.Control.extend({
defaults: {
message: "Hello World"
}
}, {
init: function(){
this.element.text( this.options.message );
}
});
new Message( "#el1" ); //writes "Hello World"
new Message( "#el12", { message: "hi" } ); //writes hi
Processors
can.Control already has processors for these events:
can.Control 可处理的事件如下:
change、click、contextmenu、dblclick、focusin、focusout、keydown、keyup、keypress、mousedown、mouseenter、mouseleave、mousemove、mouseout、mouseover、mouseup、reset、resize、scroll、select、submit
Route
Route events will be triggered whenever the route changes to the route part the control is listening to
当can.control监听的route部分的属性变动时将会触发route事件
var Router = can.Control({
init : function(el, options) {
},
":type route" : function(data) {
// the route says anything but todo
},
"todo/:id route" : function(data) {
// the route says todo/[id]
// data.id is the id or default value
},
"route" : function(data){
// the route is empty(route为空时触发)
}
});
new Router(window);
Options
The this.options property is an Object that contains configuration data passed to a control when it is created (new can.Control(element, options))
This.options属性是一个在control创建是传递control的配置数据的Object
请查看Default中的示例代码!
Setup
Element
Map
Backup
can.Map.backup is a plugin that provides a dirty bit for properties on an Map, and lets you restore the original values of an Map’s properties after they are changed
var recipe = new can.Map({
title: 'Pancake Mix',
yields: '3 batches',
ingredients: [{
ingredient: 'flour',
quantity: '6 cups'
},{
ingredient: 'baking soda',
quantity: '1 1/2 teaspoons'
},{
ingredient: 'baking powder',
quantity: '3 teaspoons'
},{
ingredient: 'salt',
quantity: '1 tablespoon'
},{
ingredient: 'sugar',
quantity: '2 tablespoons'
}]
});
recipe.backup();
recipe.attr('title', 'Flapjack Mix');
recipe.title; // 'Flapjack Mix'
recipe.isDirty(); // true
recipe.restore();
recipe.title; // 'Pancake Mix'
Validations
The can/map/validations plugin provides validations on maps
Contact = can.Map.extend({
init : function(){
// validates that birthday is in the future
this.validate("birthday",function(birthday){
if(birthday > new Date){
return "your birthday needs to be in the past"
}
})
}
},{});
var contact = new Contact({birthday: new Date(2012,0) })
Use errors ( [attrs…], newVal ) to read errors or to test if setting a value would create an error:
使用errors方法测试设置的值是否验证通过
Listen to changes in data
Use Model.bind(eventType, handler(event, model)) to listen to all events of type on a model and model.bind(eventType, handler(event)) to listen to events on a specific instance
使用Model.bind(eventType, handler(event, model))来监听某Model类型的事件,使用model.bind(eventType, handler(event))来监听摸model对象的的事件
一般有created、updated、destroyed三个事件
// listen for when any todo is created
Todo.bind('created', function( ev, todo ) {...})
// listen for when a specific todo is created
var todo = new Todo({name: 'do dishes'})
todo.bind('created', function( ev ) {...})
Property Changes
// listen for when the name property changes
todo.bind('name', function(ev){ })
Listening with can.Control
Todos = can.Control.extend({
"{Todo} updated" : function(Todo, ev, todo) {...}
})
Parse Model
can.Model.parseModel(data, xhr)
Expected data format: {id: 1, name : “dishes”},If your service returns data like
{ thingsToDo: {name: “dishes”, id: 5} }
假如使用findOne接受的数据是:{ thingsToDo: {name: “dishes”, id: 5} },而model对应期望的数据是{id: 1, name : “dishes”}时,可以使用如下方式处理
Task = can.Model.extend({
parseModel: function(data){
return data.thingsToDo;
}
},{});
或者使用
Task = can.Model.extend({
parseModel: "thingsToDo"
},{});
Fixture
(待续)
Mustache
Register Helpers
Eg:创建一个通用的Link
can.mustache.registerHelper('link', function(text, url) {
text = can.esc(text);
url = can.esc(url);
var result = '<a href="' + url + '">' + text + '</a>';
return can.mustache.safeString(result);
});
Iteration
迭代一组字符串数组
Template:
{{#people}}
{{.}}
{{/people}}
Data:
{
people: ["Andy", "Austin", "Justin"]
}
Result:
Andy Austin Justin
{{@index}}
The template:
<ul>
{{#each items}}
<li> {{@index}} - {{.}} </li>
{{/each}}
</ul>
Rendered with:
{ items: ['Josh', 'Eli', 'David'] }
Renders:
<ul>
<li> 0 - Josh </li>
<li> 1 - Eli </li>
<li> 2 - David </li>
</ul>
{{@key}}
The template:
<ul>
{{#each person}}
<li> {{@key}}: {{.}} </li>
{{/each}}
</ul>
Rendered with:
{ person: {name: 'Josh', age: 27, likes: 'Mustache, JavaScript, High Fives'} }
Renders:
<ul>
<li> name: Josh </li>
<li> age: 27 </li>
<li> likes: Mustache, JavaScript, High Fives </li>
</ul>
(待续)