1. Vue简介
Vue的核心组成
- 数据绑定:Vue 提供了简单的语法来将数据绑定到 HTML 元素。这使得在 UI 中显示数据变得非常容易。
- 指令:Vue 提供了一系列指令来扩展 HTML 元素的功能。例如,可以使用
v-if
指令根据条件显示或隐藏元素。 - 组件:Vue 组件是自包含的 UI 元素,可以重用于不同的页面和应用程序。
- 路由:Vue 提供了一个路由系统,允许在单页面应用程序中导航到不同的页面。
2. Vue风格
Vue 的组件可以按两种不同的风格书写:选项式 API 和组合式 API
选项式
函数、变量等数据,都会挂载到this上,是通过this去访问的
<script>
export default {
// data() 返回的属性将会成为响应式的状态
// 并且暴露在 `this` 上
data() {
return {
count: 0
}
},
// methods 是一些用来更改状态与触发更新的函数
// 它们可以在模板中作为事件处理器绑定
methods: {
increment() {
this.count++
}
},
// 生命周期钩子会在组件生命周期的各个不同阶段被调用
// 例如这个函数就会在组件挂载完成后被调用
mounted() {
console.log(`The initial count is ${this.count}.`)
}
}
</script>
组合式
当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件
<script>
export default defineComponent({
components: { NotifyMenu, LinkList, LoginCard },
setup() {
const $q = useQuasar();
const loginFormSwitch = ref(false);
const leftDrawerOpen = ref(false);
function showLogin() {
// loginFormSwitch.value = true
prompt();
}
function updateLoginSwitch(value) {
loginFormSwitch.value = value;
}
return {
prompt,
updateLoginSwitch,
loginFormSwitch,
listLink,
showLogin,
leftDrawerOpen,
toggleLeftDrawer,
};
},
});
</script>
setup语法糖(推荐)
<script setup>
components: { NotifyMenu, LinkList, LoginCard },
const $q = useQuasar();
const loginFormSwitch = ref(false);
const leftDrawerOpen = ref(false);
function showLogin() {
// loginFormSwitch.value = true
prompt();
}
function updateLoginSwitch(value) {
loginFormSwitch.value = value;
}
},
});
</script>
3. 定义变量
在Vue 3中,创建ref()
对象时,通常使用const
或let
,而不是var
。
如果你创建的ref()
对象的引用不会改变,那么应该使用const
。这是最常见的情况,因为通常我们只需要改变ref()
对象的.value
属性,而不是ref()
对象本身。
import { ref } from 'vue';
const myRef = ref(0); // myRef will always point to the same ref object
myRef.value = 1; // But we can change the value of the ref
如果你需要在后面的代码中改变ref()
对象的引用,那么应该使用let
。
import { ref } from 'vue';
let myRef = ref(0); // myRef points to a ref object
myRef = ref(1); // myRef now points to a different ref object
避免使用var
,因为它的作用域规则(函数级作用域和变量提升)可能会导致意外的行为。在现代JavaScript(包括Vue 3)开发中,let
和const
(它们都有块级作用域)是更好的选择。
4. 创建响应式状态
在Vue.js中,reactive
和ref
是用于创建响应式状态的两种不同方法。它们有一些关键的区别和使用场景。
4.1. reactive
reactive
用于将一个普通的对象转换为响应式对象。它会递归地将对象的所有属性都设为响应式属性。
特点:
- 适用于对象和数组。
- 自动深度响应式(对象内部的所有嵌套属性都会变成响应式)。
- 返回的对象仍然是一个普通的JavaScript对象,可以直接访问和操作。
4.2. ref
ref
用于创建一个包含单个值的响应式引用。它适用于基本类型(如字符串、数字、布尔值等)和对象。
特点:
- 适用于基本类型、对象、数组等。
- 对基本类型,
ref
会将值包裹在一个对象的value
属性中。 - 对对象或数组,
ref
不会递归地将属性设为响应式,需要手动解包或通过.value
访问。4.3. 总结
reactive
更适合处理复杂的对象和数组,自动进行深度响应式处理。ref
更灵活,适用于基本类型和需要单独引用的对象,可以通过.value
访问和操作。
5. Vue数据绑定
Vue.js 的数据绑定分为两种类型:单向绑定和双向绑定
5.1. 单向绑定
单向绑定用来绑定数据和属性以及表达式,可以给任何属性赋值,数据只能从data流向页面
这种绑定方式通过使用双大括号插值(Mustache语法)或v-bind
指令来实现v-bind
可以简写为 :
使用双大括号插值:
<div></div>
使用v-bind指令:
<img v-bind:src="imageSrc">
5.2. 双向绑定
双向绑定v-model=""
,只能给表单类,也就是具有value属性的元素进行数据双向绑定。双向绑定不仅可以将数据从组件的数据模型绑定到视图上,还可以将视图中的用户输入反向同步回数据模型
<input v-model="message">
5.3. 计算属性(computed properties)
计算属性是基于现有的数据属性计算出新值的属性。计算属性的结果会被缓存,只有在依赖的响应式数据发生变化时才会重新计算。计算属性可以像普通属性一样在模板中使用。
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
直接使用
<div></div>
5.4. 侦听器(watchers)
侦听器可以监听数据的变化,并在变化发生时执行相应的操作,比如发送网络请求或执行复杂的计算
watch: {
firstName(newValue, oldValue) {
// 在firstName发生变化时执行逻辑
}
}
6. Vue指令
v-text
<span v-text="msg"></span>
<!-- 和下面的一样 -->
<span></span>
v-bind
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
v-model
<input v-model="message">
v-if 和 v-else 用于根据条件来渲染或销毁HTML元素。v-if指令根据条件的真假来决定是否渲染元素,而v-else指令则与v-if一起使用,用于渲染上一个兄弟元素中未被渲染的部分
<div v-if="isVisible">
Content
</div>
<div v-else>
Alternative Content
</div>
v-for 用于循环渲染列表中的元素。可以将一个数组或对象遍历,并为每个元素生成对应的HTML
<ul>
<li v-for="item in items" :key="item.id">
</li>
</ul>
v-on 用于监听DOM事件,并在触发事件时执行相应的方法。可以绑定多个事件监听器,以及传递事件参数。
<button v-on:click="handleClick">Click me</button>
<!-- 缩写 -->
<button @click="handleClick">Click me</button>
v-show
与v-if类似,也用于根据条件来显示或隐藏HTML元素。不同之处在于,v-show只是通过修改元素的样式来控制元素的显示与隐藏,而不是将元素从DOM中添加或移除。
<div v-show="isVisible">
Content
</div>
v-html
用于将数据作为 HTML 解析并渲染到元素中。通过 v-html
,您可以动态地将包含 HTML 结构的字符串绑定到元素的内容。
<div v-html="htmlString"></div>
由于 v-html
涉及将字符串解析为 HTML,因此需要谨慎使用。使用不受信任的数据或用户输入作为 htmlString
可能导致 XSS(跨站脚本攻击)漏洞。确保在使用 v-html
时对数据进行适当的验证和过滤,以防止安全问题。
使用JavaScript表达式
使用双大括号插值来嵌入 JavaScript 表达式
<p>2</p>
2
会被渲染为 4
在模板中执行更复杂的 JavaScript 表达式
<template>
<div>
</div>
</template>
<script>
export default {
data() {
return {
};
},
methods: {
}
};
</script>
7. Vue修饰符
修饰符,用于指出一个指令应该以特殊方式绑定
.number
如果想自动将用户的输入值转为 Number 类型,可以添加一个修饰符 number 给 v-model 来处理输入值:
<input v-model.number="age" type="number">
.trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:
<input v-model.trim="msg">
8. 过滤器
Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示
9. Vue 组件
在 Vue 中,一个组件由模板、脚本和样式组成
<template>
<div>
<h1></h1>
<p></p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
data() {
return {
title: 'My Component',
message: 'Hello, Vue!',
count: 0
};
},
methods: {
increment() {
this.count++;
}
}
};
</script>
<style scoped>
h1 {
color: blue;
}
</style>
9.1. 组件的分类
根组件(App.vue)
组件之间可相互嵌套,自定义组件一般都在App.vue组件中调用
动态组件(Dynamic Components)
动态组件是根据某个条件或事件,在运行时动态选择渲染的组件。Vue 提供了 <component>
元素来实现动态组件的渲染,可以根据不同的情况渲染不同的组件
单文件组件(Single File Components)
单文件组件是将组件的模板、脚本和样式都放在一个单独的文件中进行定义的组件。这种方式可以提高代码的可维护性,并且使组件的结构更加清晰。
全局组件(Global Components)
全局组件是在 Vue 实例中全局注册的组件,可以在应用程序的任何地方使用。全局组件在整个应用程序中都是可用的,适用于多个页面或组件之间的共享。
9.2. 生命周期钩子
- beforeCreate( 创建前 )
- created ( 创建后 )
- beforeMount(挂载开始之前被调用)
- mounted(挂载完成)
- beforeUpdate(数据更新之前被调用)
- updated(数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用)
- beforeDestroy(我们将要销毁整个页面或实例时调用)
- destroyed(我们的整个页面或实例被销毁之后调用)
- activated(被 keep-alive 缓存的组件激活时调用)
- deactivated(子可以看做是beforeDestory和destoryed的替代)
9.3. 组件通信
组件之间可以通过属性传递数据(props)、事件触发与监听(emit/listen)
父组件向子组件传递数据
父子组件是一种层级关系,其中一个组件(父组件)内部使用了另一个组件(子组件)
父组件通过子组件的props选项将数据传递给子组件
父组件
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent :message="parentMessage" @update="handleUpdate" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
parentMessage: 'Hello from parent!'
};
},
methods: {
handleUpdate(message) {
console.log(message); // Output: "Hello from child!"
}
}
};
</script>
子组件
<!-- ChildComponent.vue -->
<template>
<div>
<button @click="updateParent">Send Message to Parent</button>
</div>
</template>
<script>
export default {
props: ['message'],
methods: {
updateParent() {
this.$emit('update', 'Hello from child!');
}
}
};
</script>
子组件向父组件传递数据
子组件主要通过事件传递数据给父组件
Vue 组件实例可以使用 $emit
方法触发自定义事件,其他组件可以使用 $on
方法监听这些自定义事件。这种方式适用于非父子组件之间的通信,组件之间可以通过自定义事件进行消息传递。
A组件
<!-- ComponentA.vue -->
<template>
<div>
<button @click="sendMessage">Send Message</button>
</div>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$emit('custom-event', 'Hello from Component A!');
}
}
};
</script>
B组件
<!-- ComponentB.vue -->
<template>
<div>
<p></p>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
};
},
mounted() {
this.$on('custom-event', (message) => {
this.message = message; // Update message when custom event is triggered
});
}
};
</script>