一.
DOM挂载(DOM Mounting)是指将Vue实例关联到一个指定的DOM元素上,使得该元素及其子元素受Vue的管理和控制。
具体步骤和解释:
1.首先需要创建一个Vue实例,这个实例包含了Vue应用的所有数据和方法。
const app = Vue.createApp({
data() {
return {
message: "Hello, Vue!"
};
}
});
2.挂载Vue实例:
通过调用mount
方法,将Vue实例挂载到一个存在于DOM中的元素上。
app.mount('#app');
在上面的示例中,Vue应用实例被创建并挂载到<div id="app">
元素上。挂载之后,#app
元素及其子元素的内容和属性将由Vue实例控制。这里,Vue实例中的message
数据属性会替换#app
元素中的内容,使其显示"Hello, Vue!"。
二.DOM
DOM(Document Object Model,文档对象模型)是一种编程接口,用于HTML和XML文档。它提供了一种结构化的表示方法,使得编程语言能够访问和操作文档的内容和结构。DOM将文档表示为一个树结构,其中每个节点都是文档的一部分,例如元素、属性、文本等。
DOM元素的定义
DOM元素是DOM树中的一个节点,表示HTML或XML文档中的标签。每个元素都有以下几个重要属性:
- 标签名:如
<div>
、<p>
、<a>
等。 - 属性:如
id
、class
、src
、href
等。 - 子元素:包含在该元素内部的其他元素。
- 文本内容:包含在元素内部的文本。
操作DOM元素
使用JavaScript可以访问和操作DOM元素。以下是一些常见的操作:
- 获取元素:通过
document.getElementById
、document.getElementsByClassName
、document.getElementsByTagName
等方法获取DOM元素。 - 修改内容:通过
innerHTML
、textContent
等属性修改元素的内容。 - 修改属性:通过
setAttribute
、getAttribute
等方法修改元素的属性。 - 添加/删除元素:通过
appendChild
、removeChild
等方法添加或删除元素。
在Vue.js中,一个Vue实例通常会控制一个DOM元素及其子树。然而,一个Vue应用可以包含多个Vue实例,每个实例可以控制不同的DOM元素。
Vue实例控制一个DOM元素
每个Vue实例通过el
选项或者$mount
方法挂载到一个单独的DOM元素上。例如:
<div id="app1"></div>
<div id="app2"></div><script>
new Vue({
el: '#app1',
data: {
message: 'Hello from App 1'
},
template: '<div>{{ message }}</div>'
});new Vue({
el: '#app2',
data: {
message: 'Hello from App 2'
},
template: '<div>{{ message }}</div>'
});
</script>
三.选项式API和组合式API
`setup`和你提供的代码示例之间的区别在于它们使用不同的API来定义Vue组件的逻辑和数据。虽然它们都是用于创建Vue组件,但它们采用了不同的方式:
选项式API(Options API)
你提供的代码示例使用的是选项式API,这是一种传统的Vue组件定义方式。它通过配置对象来定义组件的不同部分,例如数据、方法、计算属性、生命周期钩子等。这种方式在Vue 2中非常常见,并且在Vue 3中仍然被广泛支持。
选项式API是Vue.js最早的编写组件的方式,通过定义一个包含多个选项(data、methods、computed、watch等)的对象来创建组件。
```javascript
Vue.createApp({
data() {
return {
// 组件的数据
};
},
methods: {
// 组件的方法
divEvent1() {
alert(1);
},
divEvent2() {
alert(2);
},
}
}).mount('#app');
```
组合式API(Composition API)
`setup`是组合式API的一部分,它是在Vue 3中引入的,旨在提供更灵活和可组合的代码组织方式。通过`setup`,你可以在一个地方定义所有与组件相关的逻辑和状态,使得代码更模块化和易于维护。
组合式API在Vue 3中引入,通过使用setup
函数来定义组件逻辑,允许开发者更灵活地组合逻辑代码。
特点:
- 逻辑组合:可以将相关逻辑组合在一起,更容易复用和测试。
- 更灵活:在一个地方定义和使用状态、计算属性、方法和副作用,避免了选项式API中需要在多个选项中切换的情况。
- 可复用性:使用组合函数(Composition Functions)来抽离和复用逻辑代码,提高代码的可维护性。
以下是使用`setup`的同样功能的实现:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Composition API Example</title>
</head>
<body>
<div id="app">
<button @click="divEvent1">Click Me for Event 1</button>
<button @click="divEvent2">Click Me for Event 2</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
setup() {
// 定义方法
const divEvent1 = () => {
alert(1);
};
const divEvent2 = () => {
alert(2);
};
// 返回需要在模板中使用的变量和方法
return {
divEvent1,
divEvent2
};
}
});
app.mount('#app');
</script>
</body>
</html>
三.渲染
在Vue.js中,渲染(rendering)是将Vue组件中的数据和模板合成并转换成DOM元素的过程。这个过程包括创建虚拟DOM(Virtual DOM)、将虚拟DOM映射到真实DOM、并在数据变化时进行相应的更新。
渲染过程
-
创建实例:当你创建一个Vue实例时,Vue会解析
template
选项(或者使用render
函数)来生成一个渲染函数(render function)。 -
生成虚拟DOM:渲染函数会生成一个虚拟DOM树(Virtual DOM Tree)。虚拟DOM是用JavaScript对象表示的DOM结构,是对实际DOM的抽象。
-
挂载真实DOM:虚拟DOM生成之后,Vue会根据虚拟DOM树创建真实的DOM元素,并将其插入到DOM中。这一步被称为挂载(mounting)。
-
响应数据变化:当Vue实例中的数据发生变化时,渲染函数会重新运行生成新的虚拟DOM树。Vue会对新旧虚拟DOM树进行对比(diffing),找出变化的部分,并只更新那些需要改变的真实DOM元素。这种高效的更新方式称为“DOM diff算法”。
四.vue的生命周期
Vue.js的生命周期指的是一个Vue实例从创建到销毁的过程。每个Vue实例在其生命周期内会经历一系列的初始化步骤,这些步骤会触发一些钩子函数(也称为生命周期钩子)。开发者可以在这些钩子函数中执行自定义逻辑,以响应实例的生命周期事件。
Vue实例的生命周期钩子
-
beforeCreate:
- 在实例初始化之后,数据观测和事件配置之前被调用。
- 此时,数据和方法都尚未初始化。
-
created:
- 在实例创建完成后立即被调用。
- 实例已完成数据观测和事件配置,但尚未挂载到DOM上,$el属性不可用。
- 适合进行初始数据的获取和初始化操作。
-
beforeMount:
- 在挂载开始之前被调用。
- 在此阶段,模板已经编译成了虚拟DOM,挂载目标的DOM元素还未被替换。
-
mounted:
- 在挂载完成后被调用。
- 实例已将编译后的模板渲染成真实DOM,并替换了挂载目标。
- 可以在此操作DOM或者进行依赖于DOM的操作。
-
beforeUpdate:
- 在数据发生变化,导致重新渲染之前被调用。
- 适合在数据更新前进行一些处理操作。
-
updated:
- 在由于数据更改导致的虚拟DOM重新渲染和打补丁后调用。
- 可以在此执行依赖于DOM更新后的操作,但应避免在此期间更改数据,以避免无限循环。
-
beforeDestroy:
- 在实例销毁之前调用。
- 实例仍然完全可用,可以在此进行清理操作,比如清除定时器、取消事件监听等。
-
destroyed:
- 在实例销毁后调用。
- 调用之后,实例所有的指令绑定和事件监听器都被解除,所有的子实例也被销毁。
五.Vue路由
安装 Vue Router
首先,需要安装Vue Router。在使用Vue CLI创建的项目中,可以通过以下命令进行安装:
npm install vue-router
基本配置
配置Vue Router时,需要创建路由实例并将其传递给Vue实例。
// src/router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import About from '../views/About.vue';Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
];const router = new VueRouter({
mode: 'history', // 使用 HTML5 模式,去掉 URL 中的 #
routes
});export default router;
在Vue Router中,`path`、`name`和`component`是定义路由规则时的重要属性,它们分别起着不同的作用。
`path`
- 作用:`path`定义了URL路径,当浏览器的地址栏中的URL匹配这个路径时,会加载相应的组件。
- 格式:`path`可以是一个静态字符串,也可以包含动态参数(如`:id`)。
- 示例:
const routes = [
{
path: '/',
component: Home
},
{
path: '/about',
component: About
},
{
path: '/user/:id',
component: User
}
];
在这个示例中:
- 当URL是`/`时,会加载`Home`组件。
- 当URL是`/about`时,会加载`About`组件。
- 当URL是`/user/:id`时,会加载`User`组件,并可以通过`this.$route.params.id`获取动态参数`id`的值。
`name`
- **作用**:`name`是给路由命名,可以使用命名路由进行导航。这对于链接生成、编程式导航以及处理命名动态组件特别有用。
- **格式**:`name`是一个字符串,通常是唯一的。
- **示例**:
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
{
path: '/user/:id',
name: 'user',
component: User
}
];
使用命名路由进行导航:
```html
<router-link :to="{ name: 'home' }">Home</router-link>
<router-link :to="{ name: 'user', params: { id: 123 } }">User 123</router-link>
```
在主入口文件中引入路由
在Vue应用的主入口文件中(通常是main.js
),需要将路由实例传递给Vue实例:
// src/main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount('#app');
-
new Vue({...})
:- 创建一个新的 Vue 实例。Vue.js 应用的所有功能和逻辑都在这个实例中定义。
-
router
:- 传递了
router
对象,这是之前创建的 Vue Router 实例。通过将router
注入到 Vue 实例中,应用将启用路由功能,管理不同的 URL 和组件。
- 传递了
-
render: h => h(App)
:render
函数是 Vue.js 渲染函数的简写,用于渲染根组件App
。h
是 createElement 的别名,表示创建一个 VNode(虚拟节点)。h(App)
的意思是创建一个App
组件的虚拟节点。App
是根组件,通常定义在App.vue
文件中。
-
$mount('#app')
:$mount
方法手动地挂载 Vue 实例到 DOM 中的某个元素上。'#app'
是一个 CSS 选择器,表示将 Vue 实例挂载到 id 为app
的 DOM 元素上。
在组件中使用路由
在组件中使用路由,可以通过<router-link>
组件和<router-view>
组件。
<!-- src/App.vue -->
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</div>
</template><script>
export default {
name: 'App'
};
</script>
在这个示例中,<router-link>
组件用于创建导航链接,当点击这些链接时,URL会发生变化,并且对应的组件会被加载到<router-view>
中显示。
懒加载
在路由配置中,可以这样定义一个使用懒加载的路由:
const routes = [
{
path: '/individual-center',
name: 'IndividualCenter',
component: () => import('../views/IndividualCenter.vue')
}
];const router = new VueRouter({
mode: 'history',
routes
});new Vue({
router,
render: h => h(App)
}).$mount('#app');
-
component:
- 这是路由对象中的一个属性,用于指定当路由匹配时应该渲染的组件。
-
() => import('../views/IndividualCenter.vue')
- 这是一个箭头函数,用于动态导入组件。动态导入也被称为懒加载,它在需要的时候才会加载对应的模块,而不是在应用启动时就加载所有模块。
import
是 JavaScript 的动态模块加载语法,可以在运行时加载模块。'../views/IndividualCenter.vue'
是组件的相对路径,指向要加载的 Vue 组件文件。
为什么使用懒加载?
-
性能优化:
- 懒加载可以减小初始加载包的大小,提高应用的加载速度。只有在用户导航到特定路由时,才会加载相应的组件。
-
按需加载:
- 对于大型应用,将代码分割成多个小块,可以按需加载不同的模块,从而减少不必要的资源消耗。
六.监听属性
在 Vue.js 中,侦听属性(Watchers)是用于监听和响应数据变化的属性。当你需要在某些数据发生变化时执行特定的代码逻辑,尤其是涉及异步操作或高开销的逻辑时,侦听属性非常有用。
### 侦听属性的定义和用法
侦听属性可以在 Vue 实例中通过 `watch` 选项来定义。每个侦听器会监控指定的数据属性,并在该属性发生变化时执行一个回调函数。
#### 基本用法
以下是一个基本示例,展示了如何使用侦听属性:
```javascript
var vm = new Vue({
el: '#app',
data: {
firstName: 'John',
lastName: 'Doe',
fullName: 'John Doe'
},
watch: {
firstName: function (newVal, oldVal) {
this.fullName = newVal + ' ' + this.lastName;
},
lastName: function (newVal, oldVal) {
this.fullName = this.firstName + ' ' + newVal;
}
}
});
```
在这个例子中,当 `firstName` 或 `lastName` 发生变化时,对应的侦听器会被触发,并更新 `fullName`。
#### 深度侦听
对于嵌套的对象或数组,你可以使用 `deep` 选项来进行深度侦听。
```javascript
var vm = new Vue({
el: '#app',
data: {
user: {
firstName: 'John',
lastName: 'Doe',
address: {
city: 'New York'
}
}
},
watch: {
user: {
handler: function (newVal, oldVal) {
console.log('User changed:', newVal);
},
deep: true
}
}
});
```
在这个示例中,当 `user` 对象中的任何属性(如 `address.city`)发生变化时,侦听器会被触发。
#### 即时侦听
默认情况下,侦听器在首次绑定时不会立即执行。如果你需要在绑定时立即执行回调函数,可以使用 `immediate` 选项。
```javascript
var vm = new Vue({
el: '#app',
data: {
firstName: 'John'
},
watch: {
firstName: {
handler: function (newVal, oldVal) {
console.log('First name changed:', newVal);
},
immediate: true
}
}
});
```
在这个示例中,侦听器在绑定时会立即执行一次回调函数,并输出当前的 `firstName` 值。
### 侦听属性的应用场景
侦听属性非常适用于以下场景:
1. **异步操作**:如在数据变化时进行 API 调用。
2. **高开销操作**:如在数据变化时执行复杂的计算或处理。
3. **深度监听对象或数组**:如监听嵌套对象或数组中的变化。
通过侦听属性,开发者可以精确控制数据变化时的响应逻辑,从而使应用程序更加灵活和高效。
七.AJAX与Axios框架
AJAX(Asynchronous JavaScript and XML)和Axios是用于在网页中进行异步数据请求的技术和库,尽管它们的功能相似,但它们在使用方式和特性上有一些区别。
AJAX(Asynchronous JavaScript and XML)
AJAX是一种技术集合,用于在不重新加载整个网页的情况下从服务器请求数据并更新网页内容。虽然名字中包含XML,但实际上AJAX可以处理多种数据格式,包括JSON、HTML、纯文本等。
#### 特点:
1. **异步操作**:通过AJAX,可以在后台进行数据请求,用户界面不被阻塞,提升用户体验。
2. **跨浏览器支持**:AJAX是由原生JavaScript支持的技术,适用于所有现代浏览器。
3. **灵活性**:能够通过XMLHttpRequest对象(或Fetch API)进行高度定制化的请求,满足复杂的需求。
#### 使用方式:
```javascript
// 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();// 配置请求
xhr.open('GET', 'https://api.example.com/data', true);// 设置响应处理函数
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(JSON.parse(xhr.responseText));
} else {
console.error('Request failed');
}
};// 发送请求
xhr.send();
```
### Axios
Axios是一个基于Promise的HTTP库,用于在浏览器和Node.js环境中发送HTTP请求。它对AJAX进行了封装,简化了请求的配置和处理。
#### 特点:
1. **基于Promise**:Axios返回的是Promise对象,便于进行链式调用和异步操作。
2. **自动转换数据**:Axios会自动将JSON数据解析为JavaScript对象。
3. **支持拦截器**:可以在请求或响应被处理之前拦截它们,便于进行统一处理或错误处理。
4. **简化的API**:相较于原生XMLHttpRequest,Axios的API更加简洁和易于使用。
5. **广泛的浏览器支持**:支持IE9+,并且可以在Node.js环境中使用。
#### 使用方式:
```javascript
// 使用Axios进行GET请求
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Request failed', error);
});// 使用Axios进行POST请求
axios.post('https://api.example.com/data', {
key: 'value'
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Request failed', error);
});
```
#### 安装与导入:
```bash
npm install axios
```
```javascript
// 导入Axios
const axios = require('axios'); // Node.js
import axios from 'axios'; // ES6
```
### 总结
AJAX和Axios都可以用于实现异步数据请求,但Axios提供了更简洁和功能更强大的接口,使开发者能够更方便地处理HTTP请求和响应。对于简单的需求,使用原生AJAX可能就足够了,但对于复杂的应用程序,Axios通常是更好的选择。
八.let
、var
或 const
let
是 JavaScript 中用来声明变量的一种方式。
let
声明的变量只在其所在的代码块(由{}
包围的代码区域)中可见。- 这与
var
不同,var
声明的变量是函数作用域或全局作用域的。
在 JavaScript 中,不使用 let
、var
或 const
直接声明变量是可以的,但这是不推荐的做法。直接声明的变量会被隐式地创建为全局变量,这会带来一些潜在的问题和副作用。
九.reactive
reactive
是 Vue 3 中提供的一个函数,用于创建响应式状态。响应式状态是指当状态发生变化时,依赖于该状态的组件会自动更新。reactive
函数可以将一个普通的 JavaScript 对象转换为响应式对象,使得对象的每个属性都具有响应性。
在Vue 3中,使用Composition API时,会遇到ref
和reactive
的概念。你提到的 let allQuantity
可能是通过 ref
定义的响应式变量。下面是一个简化的示例,解释为什么你需要使用 .value
来赋值:
import { ref } from 'vue';
let allQuantity = ref(0);
// 假设你从某个API获取了数据,并将其赋值给 allQuantity
allQuantity.value = res.result;
为什么需要 .value
ref
是一个响应式引用,允许你将基本类型(如数字、字符串、布尔值等)和对象变成响应式的。ref
返回一个对象,这个对象有一个 value
属性,该属性存储了实际的值。当你需要访问或修改这个值时,必须通过 .value
来操作。
这是因为 ref
的设计目的是为了确保引用类型(即使是基本类型)能够在 Vue 的响应式系统中正常工作。通过使用 ref
,Vue 能够在后台跟踪这些值的变化,并自动更新依赖这些值的组件。
示例
以下是一个更详细的示例,展示如何在 Vue 3 中使用 ref
和 .value
:
<template>
<div>
<p>Quantity: {{ allQuantity }}</p>
<button @click="fetchData">Fetch Data</button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
let allQuantity = ref(0);
const fetchData = async () => {
// 假设这里调用了某个API并得到了返回结果
let res = await someApiCall();
allQuantity.value = res.result; // 使用 .value 来赋值
};
return {
allQuantity,
fetchData
};
}
};
</script>
当你在Vue 3的Composition API中使用ref
时,必须通过.value
来访问和修改存储在ref
中的值。这是Vue设计的一部分,用于确保响应式系统能够正确地跟踪和更新这些值。如果你不使用.value
,你将无法正确访问或修改这些响应式引用中的实际值。
十.计算属性
在 Vue.js 中,计算属性(computed properties)是一种定义在 Vue 实例上的属性,它们依赖于其他数据属性,并且在其依赖的数据属性发生变化时自动重新计算。计算属性是基于其依赖进行缓存的,只有当其依赖的数据发生变化时才会重新计算,否则会使用缓存的值。这使得计算属性在需要基于现有数据进行复杂计算时非常高效。
### 计算属性的定义和使用
计算属性通常定义在 Vue 实例的 `computed` 选项中。下面是一个简单的示例:
```html
<!DOCTYPE html>
<html>
<head>
<title>Vue Computed Properties</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="app">
<p>Original message: {{ message }}</p>
<p>Reversed message: {{ reversedMessage }}</p>
</div><script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
});
</script>
</body>
</html>
十一.组件
组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:
这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。Vue 同样也能很好地配合原生 Web Component。如果你想知道 Vue 组件与原生 Web Components 之间的关系,可以阅读此章节。
当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue
文件中,放在components文件夹中,方便重用
子组件和父组件
我们将某段代码封装成一个组件,而这个组件又在另一个组件中引入,而引入该封装的组件的文件叫做父组件,被引入的组件叫做子组件。