yutent edited this page
模板
模板语法基于原生的字符串模板, 并实现了一套指令, 提供类似
vue
的API.
基础用法示例
import { html, Component } from 'wkit'
class Foo extends Component {
render() {
return html`
<h1>Hello Wkit!</h1>
`
}
}
渲染变量
class Foo extends Component {
static props = {
name: 'Wkit'
}
...
render() {
return html`
<h1>Hello ${this.name}!</h1>
`
}
}
列表渲染
类似于
React
的语法, 框架会自动拼接数组, 无需自己调用join()
方法(纯文本渲染时, 等同于普通变量输出, 有额外格式要求时请手动join()
)。
class Foo extends Component {
static props = {
name: 'Wkit',
list: ['foo', 'bar']
}
...
render() {
return html`
<h1>Hello ${this.name}!</h1>
<pre>
纯文本渲染:
${this.list}
</pre>
带dom结构的渲染:
<ul>
${
this.list.map((it, i) => html`<li>${i + 1}: ${it}</li>`)
}
</ul>
`
}
}
条件渲染
限制于原生的字符串模板的语法限制, 不支持复杂的流程语句, 所以只能用
三元表达式
等简单的表达式来实现。v1.12.0 起, 可使用
when()
方法代替三元表达式;which()
方法代替switch
流程语句。
class Foo extends Component {
static props = {
name: 'Wkit',
avatar: ''
}
...
render() {
return html`
<h1>Hello ${this.name || 'Wkit'}!</h1>
${
this.avatar ? html`<img src=${this.avatar}>` : html`<wc-avatar name=${this.name}></wc-avatar>`
}
`
}
}
节点属性绑定
这个, 在上一个例子中, 已经有用到了, 模板中的节点属性, 可以加引号, 也可以不加, 效果上完全一致, 区别只是不加引号有语法高亮。
另外, 还引入了一个特殊的绑定语法, 跟
vue
一样, 在属性名前加冒号:
, 带冒号的属性, 赋值时是直接赋值的, 而不是调用setAttribute()
, 即意味着, 你可以通过这种方式, 传递复杂的数据类型。另外, 由于字符串模板的原理与
vue/react
等框架不一样, 要实现双向绑定, 需要借助live()
方法(详见下文)。
class Foo extends Component {
static props = {
name: 'Wkit',
info: {age: 18, height: 177}
}
...
render() {
return html`
<h1>Hello ${this.name || 'Wkit'}!</h1>
<wc-user-card
name=${this.name}
:info=${this.info}
>
</wc-user-card>
`
}
}
事件绑定
框架内置了强大又友好的事件绑定机制, 语法和
vue
类似,@xx=yy
, 即可向所在节点添加xx
事件的监听。事件回调支持使用匿名函数, 框架内部会修正该函数的
this
指向; 利用这个特性, 可以实现列表渲染中动态传递参数给回调函数。绑定在组件内的事件, 在组件移除出文档树时,均会自动释放, 无需手动
unbind
。(v1.6.0
起支持)
class Foo extends Component {
static props = {
count: 0
}
...
handleClick(ev) {
this.count++
}
render() {
return html`
<h1>total click ${this.count}</h1>
<button @click=${this.handleClick}>click +1</button>
<!-- 也可以使用匿名函数 -->
<button @click=${ev => this.count++}>click +1</button>
<!-- 非箭头函数也可以用, 非箭头函数的this, 同样是指向实例本身 -->
<button @click=${function(ev){ this.count++ }}>click +1</button>
`
}
}
事件绑定之 -- 修饰符
v1.9.0
起, 采用全新的事件机制, 支持以下修饰符, 可支持同时写多个修饰符。
.stop
阻止事件冒泡.prevent
阻止默认事件.self
仅当 event.target 是元素本身时才会触发事件处理器.capture
与原生一致的逻辑.once
与原生一致的逻辑.passive
与原生一致的逻辑
html`<button @click.stop=${this.handleClick}>click me</button>`
html`<button @click.stop.prevent=${this.handleClick}>click me</button>`
特殊属性之 -- ref
v1.5.11
起, 完整支持ref
绑定, 语法为ref=xx
。后续(mounted
之后), 可以通过this.$refs.xx
, 获取续写的节点对象, 无行为与vue
基本一致。ref绑定, 支持静态值, 支持变量赋值(包括在循环中使用)。
通常用于在组件内部做一些DOM操作, 而无需自己使用选择器来获取节点对象。
特殊属性之 -- #animation
v1.8.0
起, 支持动画配置, 并内置fade, scale, bounce, rotate
4种简单动画。
v1.8.4
额外增加2种动画micro-bounce, slide
。
v1.10.1
增加immediate
设定, 允许动画在节点加载时自动执行。
动画配置, 支持以下4个
type<String>
, 动画类型, 指的是内置的6种动画名字, 默认fade
。immediate<Boolean>
, 是否立即执行, 默认否。duration<Number>
, 动画的时长, 单位毫秒, 默认200毫秒。custom<Array/Object>
, 自定义动画, 如果内置的动画不满足需求, 可以自定义, 语法详见 HTML的Element.animate
文档。
class Foo extends Component {
static animation = {
type: 'fade', // 可以是6种内置之一
// 如果内置的动画不满足需求, 可以自定义, 语法详见 HTML的`Element.animate`文档
custom: [
{opacity: 0, ...}, // 阶段样式定义
{opacity: 0.5, ...},
...
]
}
}
// 声明之后, 便可在适当时机, 手动触发动画
// 执行出场动画
// this.$animate()
// 执行离场动画
// this.$animate(true)
对组件内的节点配置动画
class Foo extends Component {
render() {
// 配置同上
let options = {
type: 'fade'
}
return html`<div ref="foo" #animation=${options}>这个是有动画的节点</div>`
}
}
// 声明之后, 便可在适当时机, 手动触发动画
// 出场动画
// this.$refs.foo.$animate()
// 离场动画
// this.$refs.foo.$animate(true)
双向绑定
上面提到过, 由于模板机制的原因, 双向绑定需要借助
live()
方法实现, 当然, 也可以自行监听事件实现。
注意:
live()
方法是v1.12.0开始才支持。
import { html, live, Component } from 'wkit'
class Foo extends Component {
static props = {
value: ''
}
render() {
return html`
<!-- 自行监听input事件实现 -->
<input value=${this.value} @input=${ev => (this.value = ev.target.value)} >
<!-- 借助live()实现 -->
<input value=${live.bind(this, 'value')} >
`
}
}
属性绑定之样式设置
style
和class
这2种设置样式的属性, 比较特殊, 往往会有多个值, 以及多种条件, 所以框架内置了2个方法classMap
和styleMap
, 用于简化绑定设置。
let classes = classMap({
foo: true,
bar: this.bar,
['goo-' + this.id]: true
})
let styles = styleMap({
width: '888px',
height: '200px',
backgroundColor: '#f30'
})
html`
<div class=${classes} style=${styles}>demo</div>
`