由于工作接手的项目需要,本文主要针对 Vue 的选项式 API 编写。
本文的例子主要来自 Vue 的官方互动教程:https://cn.vuejs.org/tutorial/#step-1;官方更详细的指南文档:https://cn.vuejs.org/guide/introduction.html。
组件
Vue 组件有三个主要部分:script、template 和 style;script 中写 JavaScript、template 中写 HTML、style 中写 CSS。
<script>
export default {
data() {
return {
message: 'Hello World!',
}
}
}
</script>
<template>
<p>{{ message }}</p>
</template>
<style>
p {
color: red;
}
</style>
script 中:
- export default 用于导出组件定义(打包),以便在其他 Vue 组件中使用;
- data 选项定义了组件数据,类似面向对象中的字段;其他选项还有例如 methods、computed 等;
- return 就相当于各种语言函数中那一句 return。
template 中用到了 Mustache 插值,将在下一节讲解。
style 中是简单的 CSS。
绑定
本节主要涉及内容如下:
- Mustache 映射文本;
- computed 根据依赖项更新映射;
- v-bind 映射标签属性;
- v-on 监听事件并调函数;
- v-model 实现两处数据同步更新;
- watch 可在 v-model 基础上实现调函数。
Mustache 插值
将任何有效的 JavaScript 表达式放在 HTML 中,并用双大括号包围,表达式将被解析为文本。下面依次举例解析字符串、数字、布尔值、数组、对象、js 表达式、Vue 实例的数据属性和计算属性:
<p>{{ 'Hello, Vue!' }}</p>
<p>{{ 42 }}</p>
<p>{{ true }}</p>
<p>{{ [1, 2, 3] }}</p>
<p>{{ { name: 'John', age: 25 } }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
<p>{{ message }}</p>
<p>Count is: {{ counter.count }}</p>
computed 计算属性
computed 可根据其依赖的数据计算出一个新的值,依赖变化时则重新计算;可用 Mustache 直接引用 computed 方法。
<script>
export default {
data() {
return {
text: 'Hello, World!'
};
},
computed: {
textLength() {
return this.text.length;
}
}
};
</script>
<template>
<div>
<p>Text: {{ text }}</p>
<p>Length: {{ textLength }}</p>
</div>
</template>
v-bind 属性绑定
v-bind 用于将 Vue 实例(常常在 script 中定义)中一个数据属性绑定到 HTML 中一个标签属性。
以下例子将 Vue 实例中的 titleClass 数据属性绑定到了 p 标签的 class 属性上:
<script>
export default {
data() {
return {
titleClass: 'title'
}
}
}
</script>
<template>
<p :class="titleClass">Red</p>
</template>
<style>
.title {
color: red;
}
</style>
v-on 事件绑定
v-on
指令用于监听 DOM 事件,@
后跟动作和与动作绑定的方法,例如 @click="increment"
就表示 click 时调用 increment 方法。
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
</script>
<template>
<button @click="increment">count is: {{ count }}</button>
</template>
v-model 双向绑定
可以同时使用 v-bind 和 v-on 来在表单的输入元素上创建双向绑定,Vue 中提供了 v-model 来简化表达;v-model 也支持多选框、单选框、下拉框等。
<script>
export default {
data() {
return {
text: ''
}
}
}
</script>
<template>
<input v-model="text" placeholder="Type here">
<p>{{ text }}</p>
</template>
watch 侦听器
单纯 v-model 只能实现对数据的双向绑定,而不能调用函数或方法,后者可以通过侦听器实现。
<template>
<div>
<input v-model="inputText" type="text" placeholder="输入文字">
<p>输入的文字:{{ inputText }}</p>
<p>文字长度:{{ textLength }}</p>
</div>
</template>
<script>
export default {
data() {
return {
inputText: '',
textLength: 0,
};
},
watch: {
inputText(newValue, oldValue) {
// 当inputText属性发生变化时触发的回调函数
this.textLength = newValue.length;
},
},
};
</script>
流程控制
v-if 条件渲染
使用 v-if 指令来有条件地渲染元素。v-if 后面的表达式可以是任何能被解析为布尔值的 JavaScript 表达式;它还可以可与 v-else、v-else-if 组合使用。
<script>
export default {
data() {
return {
awesome: true
}
},
methods: {
toggle() {
this.awesome = !this.awesome
}
}
}
</script>
<template>
<button @click="toggle">toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no</h1>
</template>
v-for 列表渲染
v-for 用于简洁地渲染列表。
<script>
// 给每个 todo 对象一个唯一的 id
let id = 0
export default {
data() {
return {
todos: [
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
]
}
}
}
</script>
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
<!-- todo 是一个局部变量,表示当前正在迭代的数组元素 -->
</ul>
</template>
生命周期和模板引用
生命周期钩子函数允许我们在组件不同的阶段执行自定义的逻辑,例如数据的初始化、异步请求、DOM 操作、清理等操作。
模板引用使用 this.$refs.自定义属性名称
来在 script 中访问 template 元素;被引元素处需用 ref
属性指定。模板引用可以对被引元素直接执行一些 DOM 操作,例如修改 textContent:this.$refs.pElementRef.textContent = 'Mounted!'
:
<script>
export default {
mounted() {
this.$refs.pElementRef.textContent = 'Mounted!'
}
}
</script>
<template>
<p ref="pElementRef">Hello!</p>
</template>
常用的生命周期钩子函数有:
beforeCreate()
:在实例被创建之前调用,此时数据观测和事件配置尚未完成。created()
:在实例创建完成后调用,此时实例已经完成数据观测,可以访问到数据、计算属性和方法,但尚未挂载到 DOM 上。beforeMount()
:在实例挂载到 DOM 元素之前调用,此时模板编译已完成,但尚未将模板渲染成最终的 DOM。mounted()
:在实例挂载到 DOM 元素后调用,此时实例已经完成 DOM 渲染,可以访问到挂载后的 DOM 元素。常用于执行一些需要 DOM 操作的逻辑。beforeUpdate()
:在数据更新之前调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以用于在更新之前进行一些额外的操作。updated()
: 在数据更新之后调用,发生在虚拟 DOM 重新渲染和打补丁之后。可以用于执行一些更新后的操作。beforeUnmount()
:在实例销毁之前调用,此时实例仍然完全可用。unmounted()
:在实例销毁后调用,此时实例的所有指令和事件监听器都已经被移除,可以进行一些清理操作。
多组件
引入子组件
引入子组件实现嵌套。方法如下:
- import 指定名称,名称可以自定义,但建议与要引入的文件名相同;
- 在 script 中的 components 列表里注册子组件;
- 在 template 中用组件名标签引入,例如
<ChildComp />
。
举例如下:
父组件 App.vue 内容如下:
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
}
}
</script>
<template>
<ChildComp />
</template>
子组件 ChildComp.vue 内容如下:
<template>
<h2>A Child Component!</h2>
</template>
props
相当于跨组件的 v-bind,子组件可以通过 props 从父组件接受数据。props 的使用方法如下:
- 在子组件中定义 props,类似声明变量;
- 在父组件中引入并注册子组件;
- 在父组件中 v-bind 引用 props,类似给变量赋值。
举例如下:
父组件 App.vue:
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
greeting: 'Hello from parent'
}
}
}
</script>
<template>
<ChildComp :msg="greeting" />
</template>
子组件 ChildComp.vue:
<script>
export default {
props: {
msg: String
}
}
</script>
<template>
<h2>{{ msg || 'No props passed yet' }}</h2>
</template>
emits
相当于跨组件的 v-on,子组件可以通过 emits 向父组件触发事件。emits 的使用方法如下:
- 在子组件中定义 emits,类似声明函数;
- 在父组件中引入并注册子组件;
- 在父组件中 v-on 引用 emits,类似调用父组件中定义的函数;
举例如下:
父组件 App.vue:
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
childMsg: 'No child msg yet'
}
}
}
</script>
<template>
<ChildComp @response="(msg) => childMsg = msg" />
<p>{{ childMsg }}</p>
</template>
子组件 ChildComp.vue:
<script>
export default {
emits: ['response'],
created() {
this.$emit('response', 'hello from child')
}
}
</script>
<template>
<h2>Child component</h2>
</template>
slots 插槽
父组件可以通过 slots 将模板片段传递给子组件。子组件 slot 标签内的内容将被父组件 ChildComp 标签内的内容替换。举例如下:
父组件 App.vue:
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
}
}
</script>
<template>
<ChildComp>Message from parent</ChildComp>
</template>
子组件 ChildComp.vue:
<template>
<slot>Fallback content</slot>
<p>Message from child</p>
</template>
发表回复
要发表评论,您必须先登录。