模板语法
Vitarx 使用 JSX 作为模板语法。本页介绍 JSX 中常用的绑定方式,包括表达式、样式、事件和属性绑定。
JSX 表达式
在 JSX 中,使用 {} 包裹 JavaScript 表达式,表达式的结果会被渲染到页面上:
import { ref, createApp } from 'vitarx'
function App() {
const name = ref('Vitarx')
const version = 4
return (
<div>
<p>框架名称: {name}</p>
<p>版本号: {version}</p>
<p>计算结果: {1 + 1}</p>
</div>
)
}
createApp(App).mount('#app')你可以放入任何 JavaScript 表达式,包括函数调用、三元运算等:
<p>{name.value.length > 5 ? '名称较长' : '名称较短'}</p>INFO
在模板中使用 ref 时,不需要写 .value,框架会自动解包。例如 {name} 等同于 {name.value}。
class 绑定
字符串绑定
直接传入字符串:
<div class="container">内容</div>对象绑定
使用对象动态控制类名,属性名为类名,值为布尔值——值为 true 时添加该类名:
import { ref, createApp } from 'vitarx'
function App() {
const isActive = ref(true)
return <div class={{ active: isActive, disabled: false }}>内容</div>
}
createApp(App).mount('#app')渲染结果:<div class="active">内容</div>
数组绑定
使用数组组合多个类名:
<div class={['base', isActive.value ? 'active' : '']}>内容</div>混合使用
字符串、对象、数组可以混合使用:
<div class={['container', { active: isActive, 'no-border': true }]}>内容</div>style 绑定
对象绑定
使用对象设置内联样式,属性名使用驼峰命名:
import { ref, createApp } from 'vitarx'
function App() {
const color = ref('red')
return <div style={{ color, fontSize: '16px', marginTop: '20px' }}>彩色文字</div>
}
createApp(App).mount('#app')INFO
- CSS 属性名使用驼峰命名:
font-size→fontSize,background-color→backgroundColor - 数值类型的属性值会自动添加
px后缀(如marginTop: 20等同于marginTop: '20px')
字符串绑定
也可以直接传入 CSS 字符串:
<div style="color: red; font-size: 16px;">文字</div>事件处理
基本用法
事件使用驼峰命名(如 onClick、onInput),传入事件处理函数:
import { ref, createApp } from 'vitarx'
function App() {
const count = ref(0)
return (
<div>
<p>计数: {count}</p>
<button onClick={() => count.value++}>点击 +1</button>
</div>
)
}
createApp(App).mount('#app')事件对象
事件处理函数会接收原生事件对象作为参数:
function App() {
const handleInput = (e: Event) => {
const target = e.target as HTMLInputElement
console.log('输入内容:', target.value)
}
return <input onInput={handleInput} placeholder="请输入" />
}常用事件
| 事件名 | 说明 |
|---|---|
onClick | 点击 |
onInput | 输入 |
onChange | 变更 |
onSubmit | 提交 |
onKeyDown | 按键按下 |
onKeyUp | 按键抬起 |
onMouseEnter | 鼠标移入 |
onMouseLeave | 鼠标移出 |
onFocus | 获得焦点 |
onBlur | 失去焦点 |
展开绑定
Vitarx 支持两种方式将对象的所有属性绑定到元素上:v-bind 和 JSX 扩展语法 {...props}。注意这两种语法互斥,只能使用其中一种。
方式一:v-bind(推荐用于排除属性)
对象形式
将整个对象的属性展开到元素上:
import { createApp } from 'vitarx'
function App() {
const attrs = {
id: 'my-input',
placeholder: '请输入',
maxLength: 100
}
return <input v-bind={attrs} />
}
createApp(App).mount('#app')数组形式(排除属性)
如果你想在展开时排除某些属性,可以使用数组形式,第二个元素为要排除的属性名列表:
const attrs = {
id: 'my-input',
placeholder: '请输入',
class: 'input-field',
style: { color: 'red' }
}
// 排除 class 和 style
<input v-bind={[attrs, ['class', 'style']]} />方式二:JSX 扩展语法 {…props}(推荐用于组件)
使用标准的 JSX 扩展语法展开对象:
import { createApp } from 'vitarx'
function Button(props: { [key: string]: any }) {
return (
<button type="button" {...props}>
Click me
</button>
)
}
function App() {
const buttonProps = {
id: 'my-button',
disabled: false,
style: { padding: '10px 20px' }
}
return <Button {...buttonProps} />
}
createApp(App).mount('#app')两种方式对比
| 特性 | v-bind | {...props} |
|---|---|---|
| 排除属性 | 支持 v-bind={[obj, ['exclude']]} | 不支持 |
| JSX 标准 | 非标准 | 标准语法 |
| 适用场景 | 需要排除特定属性 | 组件透传 props |
| 互斥 | 与 {…props} 互斥 | 与 v-bind 互斥 |
WARNING
v-bind 和 {...props}不能同时使用在同一个元素或组件上,否则会导致编译错误。选择一种方式即可。
INFO
v-bind 会智能合并 class 和 style 属性,不会覆盖已有的值,而是合并在一起。
ref 绑定
绑定 DOM 元素
使用 ref 属性获取 DOM 元素的引用:
import { ref, createApp, onMounted } from 'vitarx'
function App() {
const inputRef = ref<HTMLInputElement | null>(null)
onMounted(() => {
// 挂载后自动聚焦
inputRef.value?.focus()
})
return <input ref={inputRef} placeholder="自动聚焦" />
}
createApp(App).mount('#app')ref 属性也可以传入一个回调函数,在元素挂载时调用:
function App() {
const setInput = (el: HTMLInputElement) => {
el.focus()
}
return <input ref={setInput} placeholder="自动聚焦" />
}绑定组件实例
ref 也可以绑定到组件上,获取组件通过 defineExpose 暴露的成员:
import { ref, createApp, defineExpose, onMounted } from 'vitarx'
// 子组件:通过 defineExpose 暴露方法
function Child() {
const count = ref(0)
const increment = () => {
count.value++
}
const reset = () => {
count.value = 0
}
// 暴露给父组件的成员
defineExpose({ increment, reset, count })
return <div>子组件计数: {count}</div>
}
// 父组件:通过 ref 调用子组件方法
function App() {
const childRef = ref<any>(null)
onMounted(() => {
// 调用子组件暴露的方法
childRef.value?.increment()
})
return (
<div>
<Child ref={childRef} />
<button onClick={() => childRef.value?.reset()}>重置子组件</button>
</div>
)
}
createApp(App).mount('#app')提示
组件默认不暴露任何成员。只有通过 defineExpose 显式声明的属性和方法,才能被父组件通过 ref 访问。更多用法请参考组件引用。
完整示例
下面是一个综合运用各种绑定的示例:
import { ref, createApp } from 'vitarx'
function App() {
const text = ref('')
const isFocused = ref(false)
const inputRef = ref<HTMLInputElement | null>(null)
const handleInput = (e: Event) => {
text.value = (e.target as HTMLInputElement).value
}
return (
<div style={{ maxWidth: '400px', margin: '40px auto' }}>
<h2 style={{ textAlign: 'center' }}>模板语法示例</h2>
<input
ref={inputRef}
value={text}
onInput={handleInput}
onFocus={() => {
isFocused.value = true
}}
onBlur={() => {
isFocused.value = false
}}
placeholder="请输入文字"
class={{
'input-base': true,
'input-focused': isFocused
}}
style={{
width: '100%',
padding: '8px 12px',
border: isFocused.value ? '2px solid #4a90d9' : '2px solid #ccc',
borderRadius: '4px',
outline: 'none',
fontSize: '14px',
boxSizing: 'border-box'
}}
/>
<p style={{ marginTop: '12px', color: '#666' }}>
你输入了: {text.value.length > 0 ? text : '(空)'}
</p>
<p style={{ marginTop: '8px', fontSize: '14px', color: '#999' }}>
字符数: {text.value.length}
</p>
</div>
)
}
createApp(App).mount('#app')下一步
- 响应式状态 — 深入学习
ref和reactive的用法