主题
v-model
组件
组件 v-model 转换为 Vue 2 data.model:
jsx
<ModelInput v-model_trim={this.form.name} />支持成员表达式。Options API 中使用 this.$set;setup render 中对齐 composition render-instance sugar,按需注入 getCurrentInstance().proxy.$set。
原生控件
| 控件 | 支持内容 |
|---|---|
| text input | composing guard、lazy、trim、number |
| textarea | lazy、trim、number |
| checkbox | 单值、数组、true-value、false-value |
| radio | value、number |
| select | 单选、多选、number |
| range | input/change 事件策略 |
完整示例
vue
<script lang="jsx">
import ModelInput from '../shared/ModelInput.vue'
export default {
name: 'VModelDemo',
components: { ModelInput },
data() {
return {
form: { name: 'Oxc' },
text: ' trim me ',
lazyText: 'textarea',
checks: ['A'],
enabled: 'yes',
choice: 'B',
selected: 2,
multiple: ['A']
}
},
render() {
return (
<article class="demo-card wide-card">
<span class="case-label">v-model 全类型</span>
<h3>组件与原生表单</h3>
<div class="form-grid">
<ModelInput label="组件 model + trim + $set" vModel_trim={this.form.name} />
<label class="field-row"><span>input trim</span><input class="control" vModel_trim={this.text} /></label>
<label class="field-row"><span>textarea lazy</span><textarea class="control" vModel_lazy={this.lazyText} /></label>
<label><input type="checkbox" value="A" vModel={this.checks} /> A</label>
<label><input type="checkbox" value="B" vModel={this.checks} /> B</label>
<label><input type="checkbox" true-value="yes" false-value="no" vModel={this.enabled} /> enabled</label>
<label><input type="radio" value="A" vModel={this.choice} /> A</label>
<label><input type="radio" value="B" vModel={this.choice} /> B</label>
<select class="control" vModel_number={this.selected}>
<option value="1">one</option><option value="2">two</option>
</select>
<select class="control" multiple vModel={this.multiple}>
<option value="A">A</option><option value="B">B</option><option value="C">C</option>
</select>
</div>
<pre>{JSON.stringify({ form: this.form, text: this.text, checks: this.checks, enabled: this.enabled, choice: this.choice, selected: this.selected, multiple: this.multiple }, null, 2)}</pre>
</article>
)
}
}
</script>setup render-instance
当 setup 中的 v-model 绑定到成员表达式时,编译器生成的 $set、_n、_q、_i 会改为通过捕获的 Vue 2 render instance 调用。业务源码本身不能使用 this。
vue
<script lang="tsx">
import { defineComponent, reactive } from 'vue'
import ModelInput from '../shared/ModelInput.vue'
export default defineComponent({
name: 'SetupRenderInstanceSfc',
setup() {
const form = reactive({
name: '',
amount: 1,
skills: [] as string[]
})
return () => (
<article class="demo-card">
<span class="case-label">composition render instance</span>
<h3>setup() 中的 v-model 运行时辅助</h3>
<p>
源码没有使用 this;编译器仅为 v-model 生成的
$set、_n、_i 辅助调用捕获当前 Vue 实例。
</p>
<ModelInput
label="姓名"
placeholder="输入姓名"
vModel={form.name}
/>
<label class="field-row">
<span>数量</span>
<input
class="control"
type="number"
vModel_number={form.amount}
/>
</label>
<div class="inline-options">
{['JSX', 'TSX'].map(skill => (
<label key={skill}>
<input
type="checkbox"
value={skill}
vModel={form.skills}
/>
{skill}
</label>
))}
</div>
<p class="result-line">
name: {form.name || '-'} · amount: {form.amount} · skills:{' '}
{form.skills.join(', ') || '-'}
</p>
</article>
)
}
})
</script>