Vue 简介

  • Vue.js是一套构建用户界面的渐进式框架。
  • Vue 只关注视图层, 采用自底向上增量开发的设计。
  • Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

使用案例

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.net/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="hello-vue" class="demo">
{{ message }}
</div>

<script>
const HelloVueApp = {
data() {
return {
message: 'Hello Vue!!'
}
}
}

Vue.createApp(HelloVueApp).mount('#hello-vue')
</script>
</body>
</html>

Vue 安装

  1. 使用 CDN 引入 Vue.js
    Staticfile CDN(国内) :https://cdn.staticfile.net/vue/3.0.5/vue.global.js
    字节跳动 CDN(国内) : https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.min.js
    unpkg:https://unpkg.com/vue@next, 会保持和 npm 发布的最新的版本一致。
    cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js

  2. NPM 方法
    由于 npm 安装速度慢,本教程使用了淘宝的镜像及其命令 cnpm,安装使用介绍参照:使用淘宝 NPM 镜像。

    1
    npm install -g cnpm --registry=https://registry.npmmirror.com

npm 版本需要大于 3.0,如果低于此版本需要升级它

查看版本
1
2
3
4
5
6
7
8
$ npm -v
2.3.0

#升级 npm
cnpm install npm -g

# 升级或安装 cnpm
npm install cnpm -g

在用 Vue.js 构建大型应用时推荐使用 cnpm 安装,cnpm 能很好地和 Webpack 或 Browserify 模块打包器配合使用,然后在命令行中运行以下命令:

1
npm init vue@latest

这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具。
如果不确定是否要开启某个功能,你可以直接按下回车键选择 No。
在项目被创建后,通过以下步骤安装依赖并启动开发服务器:

1
2
3
4
5
6
7
8
$ cd vue3-test
$ npm install
$ npm run dev
VITE v4.3.4 ready in 543 ms

➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h to show help

Vite

Vite (原名为 Vue.js 官方开发工具) 是一种新型前端构建工具,它能显著提升前端开发体验。它使用原生 ES 模块,并提供丰富的内置功能,如零配置的 HMR (Hot Module Replacement)、ESLint、TypeScript 支持等。
Vite 是一个基于 Rollup 的构建工具,它能将代码转换为浏览器可识别的模块,并在开发过程中提供 HMR (Hot Module Replacement) 功能,无需刷新浏览器即可看到更新。
Vite 与 Vue.js 无缝集成,你可以直接在项目中使用 Vite 构建 Vue 应用。
通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目,语法格式如下:

1
2
3
4
5
npm init vite-app <project-name>
# 运行项目
cd <project-name>
npm install
npm run dev

Vue 打包

打包 Vue 项目使用以下命令:

1
npm run build

执行完成后,会在 Vue 项目下会生成一个 dist 目录,该目录一般包含 index.html 文件及 static 目录,static 目录包含了静态文件 js、css 以及图片目录 images(如果有图片的话)。

如果直接双击打开 index.html,在浏览器中页面可能是空白了,要正常显示则需要修改下 index.html 文件中 js、css 文件路径。
例如我们打开 dist/index.html 文件看到 css 和 js 文件路径是绝对路径:

1
2
<script type="module" src="/_assets/index.5c4beb92.js"></script>
<link rel="stylesheet" href="/_assets/style.0637ccc5.css">

我们把 js、css 文件路径修改为相对路径:

1
2
<script type="module" src="_assets/index.5c4beb92.js"></script>
<link rel="stylesheet" href="_assets/style.0637ccc5.css">

如果还不能显示 那就是浏览器跨源问题需要禁用浏览器的同源策略, 可以百度进行查找关闭。

Vue3 创建一个 Vue 应用

应用实例​

每个 Vue 应用都是通过 createApp 函数创建一个新的 应用实例:

1
2
3
4
5
import { createApp } from 'vue'

const app = createApp({
/* 根组件选项 */
})

挂载应用​

应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串:

1
<div id="app"></div>
1
app.mount('#app')

computed vs methods

我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

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
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.staticfile.net/vue/3.0.5/vue.global.js"></script>
</head>
<body>
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>使用 computed 计算后反转字符串: {{ reversedMessage }}</p>
<p>使用 methods 计算后反转字符串: {{ reversedMessage2() }}</p>
</div>

<script>
const app = {
data() {
return {
message: 'RUNOOB!!'
}
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
},
methods: {
reversedMessage2: function () {
return this.message.split('').reverse().join('')
}
}
}

Vue.createApp(app).mount('#app')
</script>
</body>
</html>

methods

在 Vue.js 中,methods 是一个对象,它包含了你可以在 Vue 实例中调用的所有方法。这些方法可以在模板的表达式、计算属性或侦听器中被调用,或者由事件处理函数(如点击事件)调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>  
<div>
<button @click="greet">点击我</button>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
data() {
return {
message: 'Hello Vue!'
}
},
methods: {
greet() {
alert('你好,Vue!');
this.message = '你点击了按钮'; // 修改 data 中的 message
}
}
}
</script>

注意几点:

methods 中的函数可以通过 this 关键字来访问 Vue 实例的其它属性和方法。
methods 中的函数通常不会返回任何值(除非它们被用作计算属性或侦听器的处理函数),因为它们在模板中通常被用作事件处理函数。
如果你需要在 methods 中使用异步操作(如 AJAX 请求),你可能需要处理 Promise 或 async/await。
Vue 不会为 methods 中的函数自动绑定 this 上下文。你必须确保始终在 Vue 组件的上下文中调用它们,或者使用箭头函数来自动绑定 this。但是,通常建议在 Vue 的方法中使用常规的函数定义,以保持 this 的正确引用。

mounted

mounted 是组件生命周期钩子函数之一。当 Vue 实例被挂载到 DOM 并完成其初始渲染后,mounted 钩子会被调用。
mounted 钩子特别适用于执行需要在 DOM 加载后运行的代码,如操作 DOM 元素、发起 AJAX 请求或启动第三方 UI 库等。

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
<template>  
<div>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
data() {
return {
message: 'Loading...'
}
},
mounted() {
// 当组件挂载到 DOM 后执行
// 这里可以发起 AJAX 请求或操作 DOM
this.fetchData();
},
methods: {
fetchData() {
// 模拟 AJAX 请求,假设这是一个异步操作
setTimeout(() => {
this.message = 'Data loaded!';
}, 1000);
}
}
}
</script>

async 和 await

async
async 关键字用于声明一个函数是异步的。一个 async 函数总是返回一个 Promise。如果 async 函数返回一个值,那么这个值会被 Promise.resolve() 包裹并返回。如果 async 函数抛出一个错误,那么这个错误会被 Promise.reject() 包裹并返回。

await
await 关键字只能在 async 函数内部使用。它用于等待一个 Promise。当 Promise 被解决(fulfilled)时,await 表达式的值就是 Promise 的解决值(fulfillment value)。如果 Promise 被拒绝(rejected),那么 await 表达式会抛出一个错误。

事件修饰符

在处理事件时调用 event.preventDefault()event.stopPropagation() 是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。

1
2
<!-- 点击事件最多被触发一次 -->
<a @click.once="doThis"></a>

表单输入绑定:修饰符

.lazy​
默认情况下,v-model 会在每次 input 事件后更新数据 (IME 拼字阶段的状态例外)。你可以添加 lazy 修饰符来改为在每次 change 事件后更新数据:

1
2
3
4
5
6
7
<!-- 同步更新  -->
{{ mg1 }}
<input v-model="msg1" />

<!-- 在 "change" 事件后同步更新而不是 "input" -->
{{ mg }}
<input v-model.lazy="msg" />

.number
如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入:

1
<input v-model.number="age" />

.trim​
如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符:

1
<input v-model.trim="msg" />

侦听器

然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。
在选项式 API 中,我们可以使用 watch 选项在每次响应式属性发生变化时触发一个函数。

即时回调的侦听器
watch 默认是懒执行的:仅当数据源变化时,才会执行回调。
但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。举例来说,我们想请求一些初始数据,然后在相关状态更改时重新请求数据。

组件继承

组件一般在 项目根目录 src/components 目录下创建,然后在需要的地方通过 import 引入。

定义一个组件

当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC):
ButtonCounter.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
export default {
data() {
return {
count: 0
}
}
}
</script>

<template>
<button @click="count++">You clicked me {{ count }} times.</button>
</template>

使用组件

要使用一个子组件,我们需要在父组件中导入它。假设我们把计数器组件放在了一个叫做 ButtonCounter.vue 的文件中,这个组件将会以默认导出的形式被暴露给外部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
import ButtonCounter from './ButtonCounter.vue'

export default {
components: {
ButtonCounter
}
}
</script>

<template>
<h1>Here is a child component!</h1>
<ButtonCounter />
</template>

组件注册

一个 Vue 组件在使用前需要先被“注册”,这样 Vue 才能在渲染模板时找到其对应的实现。组件注册有两种方式:全局注册局部注册

全局注册
全局注册是最常用的组件注册方式。在 main.jsapp.js 文件中,我们可以用 Vue.component 方法注册一个全局组件:

1
2
3
4
5
6
import { createApp } from 'vue'
import MyComponent from './MyComponent.vue'

const app = createApp({})

app.component('MyComponent', MyComponent)

全局注册的组件可以在此应用的任意组件的模板中使用:

局部注册
局部注册是指在父组件的选项中定义子组件,而不是在全局注册。局部注册的优点是可以使组件更加模块化,更易于维护。
src/components/ComponentA.vue 文件中,我们可以这样定义一个子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
export default {
data() {
return {
count: 0
}
}
}
</script>

<template>
<button @click="count++">You clicked me {{ count }} times.</button>
</template>

然后在要使用组件的页面 进行局部注册:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
import ComponentA from '../components/ComponentA.vue'

export default {
components: {
ComponentA
}
}
</script>
<template>
<ComponentA />
</template>

传递 props

Props 是一种特别的attributes,你可以在组件上声明注册
比如 要传递给博客文章组件一个标题,我们必须在组件的 props 列表上声明它。这里要用到 props 选项:

1
2
3
4
5
6
7
8
9
10
<!-- BlogPost.vue -->
<script>
export default {
props: ['title']
}
</script>

<template>
<h4>{{ title }}</h4>
</template>

当一个值被传递给 prop 时,它将成为该组件实例上的一个属性。该属性的值可以像其他组件属性一样,在模板和组件的 this 上下文中访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
import BlogPost from '../components/BlogPost.vue'

export default {
components: {
BlogPost
},
data() {
return {
title_name: '12345',
}
}
}
</script>
<template>
<BlogPost :title="title_name" />
</template>

监听事件

我们可以通过 emits 选项来声明需要抛出的事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- BlogPost.vue -->
<script>
export default {
props: ['title'],
emits: ['enlarge-text']
}
</script>
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">Enlarge text</button>
</div>
</template>

然后在父组件中,我们可以用 @enlarge-text 监听这个事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
import BlogPost from './BlogPost.vue'

export default {
components: {
BlogPost
},
data() {
return {
posts:'some posts',
postFontSize: 1
}
}
}
</script>

<template>
<div :style="{ fontSize: postFontSize + 'em' }">
<BlogPost
:title="post"
@enlarge-text="postFontSize += 0.1"
/>
</div>
</template>

通过插槽来分配内容

这可以通过 Vue 的自定义 元素来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- AlertBox.vue -->
<template>
<div class="alert-box">
<strong>This is an Error for Demo Purposes</strong>
<slot />
</div>
</template>

<style scoped>
.alert-box {
/* ... */
}
</style>

如上所示,我们使用 作为一个占位符,父组件传递进来的内容就会渲染在这里。

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
import AlertBox from '../components/AlertBox.vue'

export default {
components: {
AlertBox
}
}
</script>

<AlertBox>
这里会被输出,占用的是slot的位置 显示
</AlertBox>

响应式 API:核心

ref()

ref() 接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value
ref 对象是可更改的,也就是说你可以为 .value 赋予新的值。它也是响应式的,即所有对 .value 的操作都将被追踪,并且写操作会触发与之相关的副作用。

1
2
3
4
5
const count = ref(0)
console.log(count.value) // 0

count.value = 1
console.log(count.value) // 1
avatar
懒觉猫先生
欢迎你们的到来!
关注我吧
最新文章
最新评论
正在加载中...
网站资讯
文章数目 :
176
已运行时间 :
本站总字数 :
119.7k
本站访客数 :
本站总访问量 :
最后更新时间 :