VUE学习
文章目录
- VUE学习
- 前置知识
- ES6模块化
- node.js 中如何实现模块化
- 前端模块化规范
- ES6模块化规范
- 在node.js中体验ES6模块化
- ES6模块化的基本语法
- Promise
- Promise 的基本概念
- 基于 then-fs 读取文件内容
- 基于 Promise 封装读文件的方法
- async/await 简化 Promise调用
- EventLoop
- JavaScript 是单线程的语言
- 同步任务和异步任务
- 宏任务和微任务
- API接口案例
- webpack
- webpack基本概念
- 环境准备
- webpack使用步骤
- webpack开发服务器
- Vue
- vue安装
- Vue创建项目
- vue自定义配置
- eslint
- 单Vue文件开发
- Vue语法
- 插值表达式
- MVVM设计模式
- 指令
- 给标签属性设置Vue变量的值
- 给标签绑定事件
- 获取表单的值
- 更新DOM对象的innerText/innerHTML
- 标签隐藏,出现
- v-for
- DOM
- 动态class
- 动态style
- 计算属性computed
- 侦听器watch
- 组件
- 基础使用
- 组件通信
- 生命周期
- 钩子函数
- 组件属性
- $refs 获取组件对象
- $nextTick 等DOM异步更新后,触发函数
- 组件 name 属性
- 动态组件
- 组件缓存
- 组件插槽
- 自定义指令
- 自定义指令注册
- 自定义指令传值
- axios
- 路由
- 组件分类
- vue-router
- 使用
- 声明式导航
- 路由重定向
- 路由404
- 路由模式设置
- 编程式导航
- 路由嵌套
- 路由守卫
- Vant移动端组件库
- Vuex
- 基础功能
- Store
- mutations
- actions
- getters
- 模块化 module
- 模块化中的命名空间 `namespaced`
- Element-UI
- 表单
- 表单校验的先决条件
- 表单校验规则
- 手动校验的实现
- VUE3
- **社区生态**
- vite
- vue3
- 创建Vue应用
- 选项API
- 组合式API
- `setup()`
- 生命周期
- `reactive()`函数
- toRef()
- toRefs()
- ref()
- computed()
- watch()
- ref属性
- 组件通信
- 果用于子组件,引用将是子组件的实例
- 组件通信
前置知识
ES6模块化
node.js 中如何实现模块化
node.js 遵循 CommonJS 的模块化规范
- 导入其他模块使用
require()
方法 - 模块对外共享成员使用
module.exports
对象
前端模块化规范
ES6 模块化之前,JavaScript 社区提出 AMD、CMD、CommonJS 等模块化规范,这些社区提出的模块化标准,存在一定的差异性与局限性,并不是浏览器与服务器通用的模块化标准
ES6模块化是官方的通用规范
ES6模块化规范
ES6模块化规范是浏览器与服务器端通用的模块开发规范
- 每个js文件都是一个独立的模块
- 导入其他模块成员使用
import
关键字 - 向外共享模块成员使用
export
关键字
在node.js中体验ES6模块化
node.js中默认仅支持CommonJS模块化规范,若想基于 node.js 体验与学习ES6的模块化语法,按照如下两个步骤进行配置
-
node -v
确保安装 v14.15.1或更高版本的node.js - 在
package.json
的根节点中添加"type":"module"
节点
npm init -y
快速初始化package.json
包管理文件
ES6模块化的基本语法
-
默认导出与默认导入
- 默认导出语法:
export default 默认导出的成员
每个模块中,只允许使用唯一的一次默认导出
- 默认导入语法:
import 接收名称 from '模块标识符'
- 默认导入时的接收名称可以是任意名称,只要是合法的成员名称即可
- 默认导出语法:
-
按需导出与按需导入
- 按需导出语法:
export 按需导出的成员
- 按需导入语法:
import {s1,s2,say} from '模块标识符'
- 每个模块中可以使用多次按需导出
- 按需导入的成员名称必须和按需导出的名称保持一致
- 按需导入时,可以使用
as
关键字进行重命名 - 按需导入可以和默认导入一起使用
- 按需导出语法:
-
直接导入并执行模块中代码
如果只想单纯地执行某个模块中的代码,并不需要模块中向外共享的成员,此时,可以直接导入并执行模块代码
-
import '模块标识符'
直接导入并执行模块中的代码
-
Promise
Promise 的基本概念
- Promise 是一个构造函数
- 可以创建 Promise 的实例
const p = new Promise()
- new 出来的 Promise 实例对象,代表一个异步操作
- 可以创建 Promise 的实例
-
Promise.prototype
上包含一个.then()
方法- 每一次
new Promise()
构造函数得到的实例对象 - 都可以通过
原型链的方式
访问到.then()
方法
- 每一次
-
.then()
方法用来预先指定成功和失败的回调函数p.then(成功的回调函数,失败的回调函数)
p.then(result->{},error=>{})
- 调用
.then()
方法时,成功的回调函数时必选的、失败的回调函数是可选的 - 如果上一个
.then()
方法返回一个新的 Promise 实例对象,则可以通过下一个.then()
继续进行处理。通过.then()
方法的链式调用,就能解决回调地狱的问题
-
.catch()
捕获错误- 在Promise 的链式操作中如果发生了错误,可以使用 Promise.prototype.cath 方法进行捕获和处理
- 如果不希望前面的错误导致后续的
.then()
无法正常执行,则可以将.catch()
的调用提前
-
Promise.all()
方法- Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的
.then()
操作
- Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的
-
Promise.race()
方法- 发起并行的Promise异步操作,只要任何一个异步操作完成,就立即执行下一步的
.then()
操作
- 发起并行的Promise异步操作,只要任何一个异步操作完成,就立即执行下一步的
import thenfs from "then-fs";
const promiseArr = [
thenfs.readFile("./files/1.txt", "utf8"),
thenfs.readFile("./files/2.txt", "utf8"),
thenfs.readFile("./files/3.txt", "utf8"),
]
// 全部异步完成
Promise.all(promiseArr).then(res=>{
console.log(res)
})
// 任意一个异步完成
Promise.race(promiseArr).then(res=>console.log(res))
基于 then-fs 读取文件内容
由于 node.js 官方提供的 fs 模块仅支持以回调函数的方式读取文件,不支持 Promise 的调用方式。因此,需要先运行如下命令npm install then-fs
,安装 then-fs 这个第三方包,从而支持基于 Promise 的方式读取文件的内容:
- then-fs 的基本使用
调用 then-fs 提供的 readFile()
方法,可以异步地读取文件的内容,它的返回值是 Promise 的实例对象。因此可以调用 .then()
方法为每个 Promise 异步指定成功和失败之后的回调函数
import thenfs from "then-fs";
thenfs.readFile("./files/1.txt", "utf8").then((r1) => {
console.log(r1);
return thenfs.readFile("./files/2.txt", "utf8");
}).then((r2) => {
console.log(r2);
return thenfs.readFile("./files/3.txt", "utf8");
}).then((r3) => {
console.log(r3);
}).catch((err)=>{
console.log(err)
});;
基于 Promise 封装读文件的方法
方法的封装要求:
- 方法名要定义为
getFile
- 方法接收一个形参path,表示要读取的文件的路径
- 方法的返回值为 Promise 实例对象
import fs from "fs";
export function getFile(path) {
// 要创建具体的异步操作,需要在new Promise()构造函数期间,传递一个 function 函数,将具体异步操作定义到 function 函数内部
return new Promise(function (resolve, reject) {
fs.readFile(path, "utf8", (err, dataStr) => {
if (err) return reject(err);//读取失败,调用失败的回调函数
resolve(dataStr);//读取成功,调用成功的回调函数
});
});
}
getFile('./files/1.txt').then(res=>console.log(res)).catch(err=>console.log(err))
getFile('./files/11.txt').then(res=>console.log(res)).catch(err=>console.log(err))
async/await 简化 Promise调用
-
async
标记函数时异步,不会阻塞其他的流程 -
await
强制等待,必须和async
配合使用
async/await 是 ES8 引入的新语法,用来简化 Promise 异步操作。在 async/await 出现之前,开发者只能通过链式.then()
方式处理Promise异步操作
-
async/await 的基本操作
import thenFs from 'then-fs' // 按照顺序读取文件 1 2 3 的内容 async function getAllFile(){ const r1 = await thenFs.readFile('./files/1.txt','utf8') console.log(r1) const r2 = await thenFs.readFile('./files/2.txt','utf8') console.log(r2) const r3 = await thenFs.readFile('./files/3.txt','utf8') console.log(r3) } getAllFile()
-
注意事项
-
如果在 function 中使用了 await ,则 function 必须被 async 修饰
-
在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行
-
import thenFs from 'then-fs' // 按照顺序读取文件 1 2 3 的内容 async function getAllFile(){ console.log('B') // awit 之后的内容会异步执行,方法调用会在此处返回 const r1 = await thenFs.readFile('./files/1.txt','utf8') const r3 = await thenFs.readFile('./files/3.txt','utf8') const r2 = await thenFs.readFile('./files/2.txt','utf8') console.log(r1,r2,r3) console.log('D') } console.log('A') getAllFile() console.log('C')
-
EventLoop
JavaScript 是单线程的语言
同一时间只能做一件事情
单线程执行任务队列的问题:
如果前一个任务非常耗时,则后续的任务就不得不一直等待,从而导致程序假死的问题
同步任务和异步任务
为了防止某个耗时任务导致程序假死的问题,JavaScript把待执行的任务分为了两类:
- 同步任务
- 非耗时任务,指的是在主线程上排队执行的那些任务
- 只有前一个任务执行完毕,才能执行后一个任务
- 异步任务
- 耗时任务,异步任务由JavaScript委托给宿主环境进行执行
- 当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
- 同步任务和异步任务的执行过程
- 1、同步任务由 JavaScript 主线程依次执行
- 2、异步任务委托给宿主环境执行
- 3、已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
- 4、JavaScript 主线程的执行栈被清空后,会读取任务队列中的回调函数,依次执行
- 5、JavaScript 主线程不断重复第4步
宏任务和微任务
JavaScript 把异步任务又做了进一步的划分,异步任务又分为两类
-
宏任务
- 异步 Ajax 请求
- setTimeout、setInterval
- 文件操作
- 其他宏任务
-
微任务
- Promise.then、.catch、.finally
- process.nextTick
- 其他微任务
-
宏任务和微任务的执行顺序
API接口案例
基于MySQL数据库 + Express 对外提供用户列表API接口服务
- 相关技术
- 第三方包 express 和 mysql2
- ES6 模块化
- Promise
- async/await
- 主要步骤
-
npm install -g nodemon
启动服务需要- 搭建项目基本结构
npm init -y
- 启用ES6模块化支持,在 package.json 中声明 “type”:“module”
- 安装第三方依赖包
npm install express@4.17.1 mysql2@2.2.5
- 创建基本的服务器
- 创建 db 数据库模块
- 创建 user_ctrl 业务模块
- 创建 user_router 路由模块
- 使用
try...catch
捕获异常
- 搭建项目基本结构
webpack
webpack基本概念
- 一个第三方模块包,用于分析,并打包代码
- 支持所有类型文件的打包
- 支持 less/sass=>css
- 支持ES6/7/8=>ES5
- 识别代码,翻译,压缩,整合打包
- 提高打开网站的速度
环境准备
-
npm install -g yarn
安装yarn -
初始化包环境
yarn init
创建一个package.json -
安装依赖包
yarn add webpack webpack-cli -D
-
package.json 中自定义打包命令
"scripts": {"build":"webpack"},
webpack使用步骤
- 打包
webpack默认打包入口在src/index.js
,执行自定义的 yarn build
命令打包,打包时终端要位于src的父级文件夹,打包生成 dist
文件夹
- webpack入口出口修改
- 新建 webpack.config.js
- 填入配置
- 修改入口文件名
配置文档:http://webpack.docschina.org/concepts/#entry
- yarn build 执行流程
-
插件自动生成html文件
http://webpack.docschina.org/plugins/html-webpack-plugin
npm install --save-dev html-webpack-plugin
-
webpack.config.js
添加配置
-
打包css文件
css-loader ,让webpack能处理css类型文件:http://webpack.docschina.org/loaders/css-loader/
style-loader,把css插入到DOM中 :https://webpack.docschina.org/loaders/style-loader/
- 安装依赖
- 添加配置
-
处理 less 文件
less-loader,webpack 将 Less 编译为 CSS 的 loader: https://webpack.docschina.org/loaders/less-loader/
-
处理图片,字体图标
webpack5,使用assert module技术实现字体文件和图片文件处理,无需配置额外loader
https://webpack.docschina.org/guides/asset-modules/
小于8kb的图片,直接转base64放在js文件中
大于8kb,单独存放
-
babel降级JS语法,兼容低版本浏览器
babel官网:http://www.babeljs.cn/
babel-loader:https://webpack.docschina.org/loaders/babel-loader/
webpack开发服务器
-
每次修改代码,重新打包,才能看到最新效果,实际工作中打包耗时
webpack开发服务器,把代码运行在内存中,自动更新,实时返回给浏览器显示
webpack-dev-server文档:https://webpack.docschina.org/configuration/dev-server/
1、下载依赖
yarn add webpack-dev-server -D
2、自定义webpack开发服务器启动命令 serve - 在package.json
"scripts":{"serve":"webpack serve"}
3、当前项目启动webpack开发服务器
yarn serve
Vue
- Vue是一个JavaScript渐进式框架
- Vue学习方式
- 传统开发模式:基于html文件开发Vue
- 工程开发方式:在webpack环境中开发Vue
vue安装
- 全局安装@vue/cli模块包
yarn global add @vue/cli
-
@vue/cli
是Vue官方提供的一个全局模块包,此包用于创建脚手架项目 -
vue -V
查看是否安装成功 - VSCode安装插件
Vetur
Vue创建项目
-
vue create vuecli-demo
项目名不能有大写字母、中文、特殊符号
-
main.js
项目打包主入口 -
App.vue
Vue页面主入口 -
index.html
浏览器运行的文件 -
App.vue
---->main,js
---->index.html
vue自定义配置
项目中没有 webpack.config.js文件,因为Vue脚手架项目用的vue.config.js
- 修改端口
module.exports = {
devServer:{
port:3000,//修改端口
open:true//浏览器自动打开
}
}
eslint
一种代码检查工具,违反规定就报错
module.exports = {
devServer:{
port:3000,//修改端口
open:true//浏览器自动打开
},
lintOnSave:false//关闭eslint检查
}
单Vue文件开发
- Vue推荐采用
.vue
文件来开发项目 -
template
里只能有一个根标签 - js独立作用域互不影响
-
style
配合scoped属性,保证样式只针对当前template内标签生效 -
Vetur
插件使用<vue>
快速创建Vue文件模板
Vue语法
插值表达式
- 标签中,直接插入vue数据变量
{{表达式}}
<template>
<div>
<h1>{{ msg }}</h1>
<h2>{{ obj.name }}</h2>
<h3>{{ obj.age > 18 ? "成年":"未成年" }}</h3>
</div>
</template>
<script>
export default {
data() {
return {
msg: "hello world",
obj: {
name: "张三",
age: 5
}
}
}
}
</script>
<style></style>
MVVM设计模式
-
Mode 模型
-
View 视图
-
VM 视图模型双向关联
-
减少DOM操作,提高效率
指令
给标签属性设置Vue变量的值
- 语法
v-bind:属性名="vue变量"
- 简写
:属性名="vue变量"
图片需要导入(import),才能使用,直接引用路径不生效
给标签绑定事件
- 语法
v-on:事件名="要执行的少量代码"
v-on:事件名="methods中的函数名"
v-on:事件名="methods中的函数名(实参)"
- 简写
@事件名="方法"
vue事件处理函数中,拿到事件对象
-
语法:
- 函数无传参,通过形参直接接收
- 函数有传参,通过
$event
指代事件对象给事件处理函数
<template> <div> <a @click="one" href="https://www.baidu.com/">不跳转百度</a><hr/> <a @click="two(10, $event)" href="https://www.baidu.com/">不跳转百度</a> </div> </template> <script> export default { methods: { //事件触发,不传值,可以直接获取事件对象 one(e) { e.preventDefault() }, //事件触发,传值,使用 $event 传递事件对象 two(num, e) { e.preventDefault() } } } </script> <style></style>>
给事件带来更强大的功能
https://cn.vuejs.org/guide/essentials/event-handling.html#event-modifiers
@事件名.修饰符="函数"
- 修饰符列表,修饰符可以链式使用
-
.stop
阻止事件冒泡,父级的时间不受影响 -
.prevent
阻止默认行为 -
.once
程序运行期间,只触发一次事件处理函数
-
给键盘事件,添加修饰符,增强能力
https://cn.vuejs.org/guide/essentials/event-handling.html#key-modifiers
-
@keyup.enter
监测回车按键 -
@keyup.esc
监测取消按键
获取表单的值
value属性和Vue数据变量,双向绑定
v-model="Vue数据变量"
- 数据双向绑定,变量变化–>视图自动同步,视图变化–>变量自动同步
- 下拉框,v-model要绑定到select标签上
- 复选框,v-model的变量值
- 非数组,关联的是复选框的checked属性,是否被选中
- 数组,关联的是复选框的value属性
-
v-model.修饰符="vue数据变量"
-
.number
以parseFloat转成数字类型 -
.trim
去除首尾空白字符 -
.lazy
在change是触发而非input时,失去焦点并且内容改变时在同步数据
-
更新DOM对象的innerText/innerHTML
-
v-text="vue数据变量"
普通字符串原样解析 v-html="vue数据变量"当成html解析
- 并且会覆盖
{{}}
插值表达式
标签隐藏,出现
-
v-show="vue数据变量"
用的是display:none隐藏,适用于频繁切换 -
v-if="vue数据变量"
直接在DOM数上移除,可以配合v-else-if
v-else
一起用
v-for
列表渲染,所在标签结构,按照数据数量,循环生成
-
语法
v-for="(值变量,索引变量) in 目标结构" :key=""
v-for="值变量名 in 目标结构"
v-for="(value,key) in 对象"
v-for="变量名 in 固定数字"
-
v-for
放在要循环的标签上 -
目标结构:数组、对象、数字
目标结构变化,触发v-for更新监测
DOM
- 真实DOM
- 虚拟DOM
虚拟DOM本质是一个JS对象,保存DOM关键信息
虚拟DOM提高更新的性能,不频繁操作真实DOM,在内存中找到变化的部分,在更新真实DOM
- diff算法
-
v-for
key对更新的影响
动态class
用v-bind
给标签class设置动态的值
-
:class="{类名:布尔值}"
布尔值为true时,类名才生效
动态style
给标签动态设置style的值
:style="{css属性名:值}"
计算属性computed
一个变量的值,依赖另外一些数据计算而来的结果
computed:{ "计算属性名"(){return "值"}}
- 计算属性也是vue数据变量,所以不要和data里重名,用法和data相同
- 计算属性的优势:计算属性对应函数执行后,会把return值缓存起来,依赖项不变,多次调用都是从缓存取值;依赖项变化,函数会自动重新执行并缓存新的值
<template>
<div>
<p>sum:{{sum}}</p>
</div>
</template>
<script>
export default {
data(){
return{
a:5,
b:10
}
},
computed:{
//计算属性也是vue数据变量,所以不要和data里重名,用法和data相同
sum(){
return this.a+this.b;
}
}
}
</script>
<style>
</style>
- 计算属性完整写法
<template>
<div>
<input type="text" v-model="val">
</div>
</template>
<script>
export default {
computed: {
// 属性名
val: {
// 设置值,触发set
set(parm) {
console.log(parm)
},
// 使用值,触发get
get() {
return "30";
}
}
}
}
</script>
<style></style>
侦听器watch
可以侦听data、computed属性值的改变
watch:{
"被侦听的属性名"(newVal,oldVal){
}
}
<template>
<div>
<input type="text" v-model="name">
</div>
</template>
<script>
export default {
data() {
return {
name: ""
}
},
//侦听器
watch: {
// name 要侦听的属性
name(newName, oldName) {
console.log(oldName, newName)
}
}
}
</script>
<style></style>
<template>
<div>
<input type="text" v-model="user.name">
<input type="text" v-model="user.age">
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: "",
age: 0
}
}
},
//侦听器
watch: {
// name 要侦听的属性
user: {
handler(newVal, oldVal) {
console.log(oldVal, newVal)
},
deep: true,//深度侦听,侦听对象内部的变化
immediate: true//在侦听开始之后立即调用
}
}
}
</script>
<style></style>
组件
- 可复用的Vue实例,封装标签,样式和JS代码
- 一个页面,可以拆分成一个个组件,一个组件就是一个整体,每个组件可以有自己独立的结构样式和行为
基础使用
每个组件都是一个独立的个体,代码里体现为一个独立的.vue文件
-
创建组件,封装要复用的标签、样式、JS代码
-
注册组件
- 全局注册:
main.js
中
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App); // 引入组件 import demo1 from "./components/demo1.vue"; // 全局注册(组件名 : 组件对象) app.component("pannel",demo1) app.mount('#app')
- 局部注册
<template> <div> <pannel2/> </div> </template> <script> // 引入组件 import demo1 from "./components/demo1.vue"; export default { // 局部注册 components:{ // 组件名 : 组件对象 "pannel2":demo1 } } </script> <style></style>
- 注册后,和标签一样使用
- 全局注册:
-
Vue组件内样式,只针对当前组件内标签生效如何做
- 在 style上添加 scoped
<style scoped></style>
- scoped 会给所有标签添加 data-v-hash 值属性,带属性选择
- 在 style上添加 scoped
组件通信
- 父传子
props
- 子组件,
props
定义变量 - 父组件,对子组件变量当做属性赋值
- 单向数据流
- 从父到子的数据流向,叫做单向数据流
- Vue规定props里的变量,本身是只读的
- 子组件修改,不通知父级,会造成数据不一致
- 子组件,
<template>
<div>
<!-- 子组件 props 变量接收 -->
<!-- 父组件,传值进去-->
<child title="资本论" auth="马克思" price="100"></child>
<child title="论语" auth="孔子" price="100"></child>
</div>
</template>
<script>
// 引入组件
import child from "./components/child.vue";
export default {
// 局部注册
components:{
// 组件名,组件对象 同名可简写
child
}
}
</script>
<style scoped></style>
<template>
<div>
<p>{{ title }}</p>
<p>{{ price }}</p>
<p>{{ auth }}</p>
<hr>
</div>
</template>
<script>
export default {
props: ['title', 'price', 'auth']
}
</script>
<style></style>
- 子传父(自定义事件)
- 父组件内,在子标签上绑定自定义事件和事件处理函数
@自定义事件名="父methods里的函数名"
- 子组件中,触发事件,在对应事件处理函数中,触发父组件绑定的自定义函数
this.$emit('事件名',参数)
- 父组件内,在子标签上绑定自定义事件和事件处理函数
<template>
<div>
<p>{{ title }}</p>
<p>{{ price }}</p>
<p>{{ auth }}</p>
<button @click="subFn">增加价格1元</button>
<hr>
</div>
</template>
<script>
export default {
props: ['title', 'price', 'auth'],
methods:{
subFn(){
//.$emit('事件名',参数)触发指定事件
this.$emit('subPrice',this.title,1)
}
}
}
</script>
<style></style>
<template>
<div>
<!-- subPrice 父组件自定义事件,绑定到子标签上 -->
<child v-for="(obj, index) in arr" :key="index" :auth="obj.auth" :title="obj.title" :price="obj.price"
@subPrice="fn" />
</div>
</template>
<script>
// 引入组件
import child from "./components/child.vue";
export default {
// 局部注册
components: {
// 组件名,组件对象 同名可简写
child
},
data() {
return {
arr: [
{ title: "资本论", auth: "马克思", price: 100 },
{ title: "论语", auth: "孔子", price: 100 }
]
}
},
methods: {
// 事件要触发的函数
fn(title, price) {
console.log(title,price)
let index = this.arr.findIndex(x => x.title === title);
this.arr[index].price += price
}
}
}
</script>
<style scoped></style>
- 跨组件通信 EventBus
生命周期
vue对象从创建到销毁的过程
钩子函数
框架内置函数,随着组件的生命周期阶段,自动执行
阶段 | 阶段之前执行的方法 | 阶段之后执行的方法 |
---|---|---|
初始化 | beforeCreate | created |
挂载 | beforeMount | mounted |
更新 | beforeUpdate | updated |
销毁 | beforeDestroy | destroyed |
- 初始化
- 执行
beforeCreate
和created
两个函数 -
created
函数触发能获取data
,不能获取真实DOM
- 执行
- 挂载
- 更新
- 销毁
- 移除一些占用的全局资源,如计时器、定时器、全局事件
组件属性
$refs 获取组件对象
- 通过id或者 ref 属性获取原生DOM标签
- 给组件起别名
ref="refStr"
,通过this.$refs.refStr
获取组件对象,可以调用组件内一切
<template>
<div>
<h1 ref="myH1" id="h">ref/id获取原生DOM</h1>
</div>
</template>
<script>
export default {
mounted(){
console.log(document.getElementById("h"))
console.log(this.$refs.myH1)
}
}
</script>
<style>
</style>
$nextTick 等DOM异步更新后,触发函数
Vue更新DOM是异步的
this.$nextTick(函数)
等DOM异步更新后触发方法中的函数
组件 name 属性
动态组件
- 多个组件使用同一个挂载点,并动态切换
- vue内置
component
组件,配合is
属性(组件名称)
组件缓存
- 频繁的切换会导致组件频繁创建和销毁,性能不高
- vue 内置
keep-alive
组件包起来要频繁切换的组件
-
组件的激活和非激活,生命周期函数
-
activated
激活时触发 -
deactivated
失去激活状态触发
-
组件插槽
组件里面数据不确定,标签不确定,通过slot
标签,让组件内接收不同的标签结构显示
-
给组件插入什么标签,组件就显示什么标签
-
使用
- 组件内用
<slot></slot>
占位 - 使用组件时,组件夹着的地方,传入标签替换
slot
- 组件内用
-
插槽默认内容
-
<slot>
内放置内容,作为默认内容 - 不给组件传标签,
slot
内容原地显示 - 给组件内传标签,则
slot
整体被替换掉
-
-
作用域插槽
-
用途:使用插槽时,想使用子组件内变量
-
使用方法
-
子组件,在
slot
上绑定属性:row="变量"
-
<template> <div> <slot :row="defaultObj">{{ defaultObj.name }}</slot> </div> </template> <script> export default { // 作用域插槽 // 1、 slot标签,自定义属性和内变量关联 // 2、使用组件,template 配合 v-slot="变量名" // 这个变量名会收集slot身上属性和值形成对象 data() { return { defaultObj: { name: "张飒", age: 20 } } } } </script> <style></style>
-
使用组件,传入自定义标签,用
template
和v-slot="自定义变量名"
-
这个变量名收
-
-