Vue
Vue是一个用于构建用户界面的渐进式框架
通过 CDN 使用 Vue
*CDN(Content Delivery Network)是一个分布式服务器网络,能够快速向用户交付静态资源(如 JavaScript、CSS、图片等)。这种方法比较简便,适合快速原型开发或小型项目。
全局构建:
1 |
|
ES 模块构建:
1 |
|
创建 Vue 应用
打算创建项目的目录打开命令行运行以下命令:
1 | npm create vue@latest |
选择功能后运行以下命令:
1 | cd <your-project-name> |
删掉一些文件和代码恢复到初始空白页面,目录大致如下:
1 | your-project: |
/src是项目的主要源代码目录,包含了所有的Vue组件、配置文件、静态资源等。/src/components
组件目录,存放可复用的Vue组件文件。/src/views
视图目录,存放页面级别的组件,对应应用的不同路由,会在其中包含页面的布局和导航逻辑。/src/router
路由目录,存放路由配置文件,定义了应用的路由规则和导航守卫。
/src/api
API请求目录,包含处理与后端服务器通信的API请求逻辑。我们项目中采用了Axios客户端库。
axios函数可以接收三个参数:url
、data
和 config
。
-
url
(必需): 这是一个字符串,表示你想要请求的服务器地址。例如:‘https://api.example.com/data’。 -
data
(可选): 这是一个对象,包含了你想要发送到服务器的数据。这个参数通常用于 POST、PUT 或 PATCH 请求。例如:{ key1: ‘value1’, key2: ‘value2’ }。当使用 POST 方法时,这些数据会被添加到请求体中。 -
config
(可选): 这是一个对象,包含了请求的配置选项。这个对象可以包含多个属性,用于定制请求的行为。以下是一些常用的配置选项:(1)headers
: 一个对象,包含了你想要设置的HTTP请求头部。(2)params
: 一个对象,包含了你想要添加到URL查询字符串中的参数。(3)responseType
: 一个字符串,指定服务器响应的数据类型。可以是 ‘arraybuffer’, ‘blob’, ‘document’, ‘json’, ‘text’ 或 ‘stream’。
对于前面介绍的三种传递参数的方法:
-
@PathVariable注解视为url参数中的变量,使用axios.post(url/${xxx}, data, config),其中data、config都可以省略
-
@RequestParam注解视为config参数中的params,使用axios.post(url, data, {params: xxx}) ,其中data不可省略,如果是空就用null填补,不然会把config当成data
-
@RequestBody注解视为data参数,使用axios.post(url, data, config),其中config可以省略
/src/assets
静态资源目录,存放图片、CSS样式表、字体文件等静态资源。/src/utils
工具函数目录,包含项目中使用的各种辅助函数和工具类,如日期处理、字符串操作、请求封装(request.ts)等。/src/App.vue
根组件,所有界面都是从这个界面发展来的,包含了应用的全局布局和导航。通过/src/main.ts
入口文件,用于创建Vue实例,引入全局样式、插件、路由、状态管理等。index.html
入口HTML文件,Vue实例将挂载到这个元素上。package.json
依赖和脚本配置文件,列出了项目的所有依赖项,并提供了用于开发和构建项目的脚本。
vue.config.ts
Vue CLI配置文件,用于配置Vue CLI,包括开发服务器、构建选项等。
.gitignore
Git忽略文件,指定git操作时应忽略的文件和目录。/public
公共资源目录,存放不会被Webpack处理的公共静态资源。
选项API与组合API
-
选项API,
data
选项写数据,methods
选项写逻辑,代码分散。 -
组合API,数据、逻辑和其他都在
setup
内写,代码集中,利于维护。
*本学习笔记选择组合API
setup
setup
是 Vue 3 组合式 API(Composition API)的核心函数,是组合式逻辑的入口。在组件初始化时执行,早于 beforeCreate
和 created
生命周期钩子。
setup
中访问 this
是 undefined
。
-
传统
<script>
语法在传统的<script>
语法中,setup
是一个函数,需要显式定义。1
2
3
4
5
6
7
8
9
10
11
12
13/* APP.vue */
<script>
export default {
name: "App",
setup() {
console.log("setup执行了");
return {
// 返回的对象中的属性和方法可以在模板中使用
message: "Hello, Vue 3!",
};
},
};
</script> -
<script setup>
语法糖在这种语法中,setup
是隐式的。所有顶级绑定(变量、函数等)都会自动暴露给模板。1
2
3
4
5/* APP.vue */
<script setup>
const message = "Hello, Vue 3!";
console.log("setup执行了");
</script>
ref 和 reactive
ref 创建
-
作用:定义响应式变量,可以是基本类型、对象类型。
-
语法:
let xxx = ref(初始值)
。
JS中操作数据需要:xxx.value
,但 <template>
中不需要 .value
,直接使用。对于let name = ref('张三')
来说,name不是响应式的,name.value是响应式的。
1 | <script setup> |
reactive 创建
-
作用:定义一个响应式对象(基本类型要用ref)
-
语法:
let 响应式对象= reactive(源对象)
。
JS无需 .value
,直接通过属性名访问。解构或赋值时可能丢失响应性,需用 toRefs
解决,把对象中的每一个属性做一次包装成为响应式数据。
⚠️reactive()
返回的是一个原始对象的 Proxy
,它和原始对象是不相等的。
1 | <script setup> |
使用原则
-
若需要一个基本类型的响应式数据,必须使用ref。
-
若需要一个响应式对象,层级不深,ref、reactive都可以。
-
若需要一个响应式对象,且层级较深,推荐使用reactive。
标签的 ref 属性
用于注册模板引用。
-
通过 ref 获取某个 DOM 元素的引用,允许直接操作该 DOM 元素(每个 HTML 元素(如
<div>
,<p>
,<button>
等)都对应一个 DOM 元素对象)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<template>
<div>
<!-- 定义一个 ref 属性,绑定到 DOM 元素 -->
<!-- 表示我们要通过 inputElement 引用这个 input 元素 -->
<input ref="inputElement" type="text" placeholder="请输入文本" />
<button @click="focusInput">聚焦输入框</button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
// 使用 ref 来获取 DOM 元素的引用
// 当组件渲染完成后,Vue 会自动把 input 元素绑定到这个引用上。
const inputElement = ref(null);
/* 定义一个方法,通过 ref 来操作 DOM 元素
inputElement 本身是一个对象,可以通过 .value 访问到实际的 DOM 元素
并调用其原生的 JS 方法 */
const focusInput = () => {
// 通过 .value 访问 DOM 元素并设置焦点
inputElement.value.focus();
};
return { inputElement, focusInput };
}
};
</script> -
通过 ref 获取到子组件的实例,允许调用子组件的方法或访问子组件的属性。
computed
创建计算属性的工具,基于响应式数据自动计算值,并且只有依赖数据变化时才重新计算。
1 | import { computed, ref } from 'vue'; |
watch
监听响应式数据变化,watch
会在其中任何一个数据变化时触发回调。
watch('需要监听的数据',数据改变执行函数,配置对象)
-
监视ref定义的基本类型数据:直接写数据名即可,监视的是其
value
值的改变。1
2
3
4
5const count = ref(0);
const name = ref("Alice");
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
console.log(`count: ${oldCount} -> ${newCount}, name: ${oldName} -> ${newName}`);
}); -
监视ref定义的对象类型数据:直接写数据名,监视的是对象的地址值,若想监视对象内部的数据,要手动开启深度监视。
-
监视reactive定义的对象类型数据,默认开启了深度监视,不需要显式设置。
1
2
3
4const user = ref({ name: 'Alice', age: 25 });
watch(user, (newValue, oldValue) => {
console.log('User changed:', newValue);
}, { deep: true }); -
监视ref或reactive定义的对象类型数据中的某个属性,一般写成函数形式。
1
2
3watch(()=>user.name,(newValue,oldValue)=>{
console.log('user.name changed:',newValue,oldValue)
},{deep:true}) -
立即触发:默认情况下,
watch
只会在数据变化时触发回调。如果希望在创建时就立即执行一次回调,可以使用{immediate: true}
。
生命周期
Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子。生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。
Vue3的生命周期:
-
创建阶段:
setup
-
挂载阶段:
onBeforeMount
、onMounted
(常用) -
更新阶段:
onBeforeUpdate
、onUpdated
(常用) -
卸载阶段:
onBeforeUnmount
(常用)、onUnmounted
Hook 是允许在特定生命周期点插入自定义代码的机制。
1 | import { onMounted } from "vue"; |
父子通信
父子组件之间的通讯主要通过两种方式:props
和 emit
。
-
父传子:父组件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// Parent.vue
<template>
<Child :message="parentMessage" />
</template>
<script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: { Child },
setup() {
const parentMessage = ref('Hello from Parent!');
return { parentMessage };
}
};
</script>子组件 通过
props
接收数据:1
2
3
4
5
6
7
8
9
10
11
12// Child.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
props: {
message: String
}
};
</script> -
子传父:父组件 监听子组件触发的事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// Parent.vue
<template>
<Child @childEvent="handleChildEvent" />
</template>
<script>
import { ref } from 'vue';
import Child from './Child.vue';
export default {
components: { Child },
setup() {
const handleChildEvent = (data) => {
console.log('Received from child:', data);
};
return { handleChildEvent };
}
};
</script>子组件 通过
emit
触发事件并传递数据:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// Child.vue
<template>
<button @click="sendToParent">Send to Parent</button>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { emit }) {
const sendToParent = () => {
emit('childEvent', 'Hello from Child!');
//第二个参数解构出emit函数,emits选项需要声明自定义事件名称
};
return { sendToParent };
}
});
</script> -
通过
provide
和inject
跨级传递
- 本文链接:https://squirrelune.github.io/cn/Web%E5%BC%80%E5%8F%91/Web%E5%BC%80%E5%8F%9106/
- 许可协议: 除特殊声明外,本站博文均采用 CC BY-NC-SA 3.0 CN 许可协议,转载请注明出处!