6. 项目 [vuejs-04]:指令 [v-model, v-bind]、计算属性、输入表单
项目 [vuejs-04] 的树形结构如下:

6.1. 主脚本 [main.js]
与前一个示例中的相同。
6.2. 主组件 [App]
[App.vue] 的代码如下:
<template>
<b-container>
<b-card>
<!-- 提示信息 -->
<b-row>
<b-col cols="8">
<b-alert show variant="success" align="center">
<h4>[vuejs-04] : directives [v-model, v-bind], attributs calculés, formulaire de saisie</h4>
</b-alert>
</b-col>
</b-row>
<Form />
</b-card>
</b-container>
</template>
<script>
import Form from "./components/Form.vue";
export default {
name: "app",
components: {
Form
}
};
</script>
组件 [App.vue] 使用了新组件 [Form](第 12、19、24 行)。
6.3. 组件 [Form]
组件 [Form] 的代码如下:
<template>
<div>
<!-- 表单 -->
<b-form>
<!-- 表单元素 -->
<b-row>
<b-col cols="4">
<b-card bg-variant="light">
<b-form-group label="Nombre d'enfants à charge" label-for="enfants">
<b-input type="text"
id="enfants"
placeholder="Indiquez votre nombre d'enfants"
v-model="enfants"
v-bind:state="enfantsValide" />
<b-form-invalid-feedback :state="enfantsValide">Vous devez saisir un nombre positif ou nul</b-form-invalid-feedback>
</b-form-group>
<!-- 按钮 -->
<b-button variant="primary" :disabled="formInvalide" @click="doSomething">Valider</b-button>
</b-card>
</b-col>
</b-row>
</b-form>
<b-row class="mt-3">
<b-col cols="4">
<b-alert show variant="warning" align="center">
<h4>enfants= {{enfants}}</h4>
</b-alert>
</b-col>
</b-row>
</div>
</template>
<!-- 脚本 -->
<script>
export default {
// 名称
name: "Form",
// 组件的静态属性
data() {
return {
// 子元素数量
enfants: ""
};
},
// 计算属性
computed: {
// 属性 [formInvalide]
formInvalide() {
return !this.enfantsValide;
},
// 属性 [enfantsInvalide]
enfantsValide() {
return Boolean(this.enfants.match(/^\s*\d+\s*$/));
}
},
// 方法
methods: {
doSomething() {
// 在验证时已知子节点数量
alert("Nombre d'enfants : " + this.enfants);
}
}
};
</script>
视觉呈现


注释
- 第 4-32 行:<b-form> 标签引入了一个 Bootstrap 表单;
- 第 6 行:<b-row> 标签在表单中插入一行;
- 第 7 行:<b-col cols=’4’> 标签引入了一列,该列占据 4 个 Bootstrap 列宽;
- 第8行:标签 <b-card> [6] 引入了一个Bootstrap卡片,即一个带有边框的区域;
- 第 9 行:<b-form-group> 标签引入了一组相互关联的表单元素。此处,文本(属性 [label])[1] 与一个输入框(属性 [label-for])相关联。 [label-for] 的值即为输入框第 12 行字段 [id] 的值;
- 第 10-14 行:<b-input> 标签 [2] 引入了一个输入框:
- 第 10 行:[type=’text’] 表示可以在输入框中输入文本。 本可以使用 [min=’val1’ max=’val2’ step=’val3’] 作为约束条件,因为预期该区域包含多个子元素。此处采用 [type=’text’] 是为了演示如何验证输入的有效性;
- 第 12 行:属性 [placeholder] [3] 用于在用户尚未输入内容时,在输入框中显示提示信息;
- 第 13 行:指令 [v-model] 将输入值与组件第 42 行的属性 [enfants] 建立双向关联:
- 当输入值发生变化时,[enfants]属性的值也会随之变化;
- 当 [enfants] 属性的值发生变化时,输入值也会随之变化,即 [2] 的内容发生变化;
- 需要理解的关键点是,通过上述机制,当用户点击按钮 [Valider] [5] 时, 第42行的[enfants]属性的值即为在[2]中输入的值;
- 第14行:指令[v-bind]建立了一条关联,一端是<b-input>标签的属性(此处为[state]),另一端是组件的属性(此处为[enfantsValide],位于第53行)。 [enfantsValide] 属性具有特殊性,因为它是一个返回该属性值的函数。此类属性被称为计算属性。计算属性位于组件的 [computed] 属性中(第 47 行)。 计算属性的使用方式与函数 [data] 中的静态属性相同:第 14 行不写 [v-bind:state=’enfantsValide()’],而是写 [v-bind:state=’enfantsValide’],且不带括号。 此外,仅通过阅读 [template] 无法区分计算属性与静态属性。为此,必须查看组件脚本的代码;
- 第14行:属性[state]将确定输入值的有效/无效状态:如果[enfantsValide]返回值[true],则输入值被视为有效;否则视为无效。 上图截图展示了当函数 [enfantsValide] 返回值 [false] 时,组件 [b-input] 的状态;
- 第 15 行:当 [2] 中的输入无效时,<b-form-invalid-feedback> 标签 [4] 会显示一条消息。 其属性 [:state=’enfantsValide’] 与第 14 行的属性 [v-bind:state=’enfantsValide’] 相同。可以省略指令 [v-bind],但必须保留符号 [:]。 因此,当属性 [enfantsValide] 的值为 [false] 时,会显示错误信息;
- 第16行:<b-group> 元素组的结束;
- 第18行:用于提交输入的按钮 [5]:
- 该按钮将显示为蓝色 [variant=’primary’];
- [:disabled="formInvalide"]:属性 [disabled] 用于启用/禁用该按钮。该属性通过 v-bind 绑定至第 49 行的计算属性 [formInvalide];
- [@click="doSomething"]:当用户点击该按钮时,将执行第59行的[doSomething]方法;
- 第 19-22 行:关闭所有已打开的标签;
- 第23-29行:在[template]中插入新行。[class=’mt-3’]表示[margin (m) top (t) égale à 3 spacers]。[spacer]是Bootstrap的间距单元。 该类在上述截图中生成 [8] 的间距。若无此类,[7] 区域将紧贴 [1-6] 区域;
- 第 24 行:占用 4 个 Bootstrap 列宽的列;
- 第 25-27 行:一个 [warning] 提示框,显示静态属性 [enfants](第 42 行)的值。 由于该属性与输入框存在双向绑定,一旦用户修改输入框内容,提示框中显示的值也会随之改变;
- 第 34-65 行:组件的代码 jS;
- 第 42 行:组件的唯一静态属性;
- 第 47-56 行:组件的计算属性;
- 第 53-55 行:若输入为正整数(前后可带空格),则视为有效;
- 第49-51行:若“子女数量”的输入有效,则表单被视为有效。通常,表单包含多个输入项,当所有输入均有效时,表单才被视为有效;
- 第58-63行:响应组件事件的组件方法。此处仅有一个事件:按钮上的[click]事件。我们仅显示输入的值,以证明能够正常访问该值;
6.4. 项目运行
修改文件 [package.json] 并运行项目:
