目录
vue 基础入门
1、解读核心关键词:框架
2、vue 的版本
3、vue 的调试工具
vue 基础入门
vite 的基本使用
1. 创建 vite 的项目
2. 梳理项目的结构
3. vite 项目的运行流程
组件的基本使用
1. 组件的注册
2. 组件之间的样式冲突问题
3. 组件的 props
4. Class 与 Style 绑定
6、自定义事件
7、组件上的 v-model
组件高级 (上)
1、watch 侦听器
2、组件的生命周期
3、组件之间的数据共享
4、vue 3.x 中全局配置 axios
组件高级 (下)
1、ref 引用
2、动态组件
3、插槽
4、自定义指令
私有自定义指令
全局自定义指令
vue 基础入门
1、解读核心关键词:框架
- vue(核心库)
- vue-router(路由方案)
- vuex(状态管理方案)
- vue 组件库(快速搭建页面 UI 效果的方案)
- vue-cli(npm 全局包:一键生成工程化的 vue 项目 - 基于 webpack、大而全)
- vite(npm 全局包:一键生成工程化的 vue 项目 - 小而巧)
- vue-devtools(浏览器插件:辅助调试的工具)
- vetur(vscode 插件:提供语法高亮和智能提示)
2、vue 的版本
vue3.x 和 vue2.x 版本的对比
3、vue 的调试工具
vue 2.x 调试工具:
vue 基础入门
vite 的基本使用
1. 创建 vite 的项目
npm init vite-app 项目名称
> cd 项目名称
> npm install
> npm run dev
2. 梳理项目的结构
- node_modules 目录用来存放第三方依赖包
- public 是公共的静态资源目录
- src 是项目的源代码目录(程序员写的所有代码都要放在此目录下)
- .gitignore 是 Git 的忽略文件
- index.html 是 SPA 单页面应用程序中唯一的 HTML 页面
- package.json 是项目的包管理配置文件
- assets 目录用来存放项目中所有的静态资源文件(css、fonts等)
- components 目录用来存放项目中所有的自定义组件
- App.vue 是项目的根组件
- index.css 是项目的全局样式表文件
- main.js 是整个项目的打包入口文件
3. vite 项目的运行流程
- App.vue 用来编写待渲染的模板结构
- index.html 中需要预留一个 el 区域
- main.js 把 App.vue 渲染到了 index.html 所预留的区域中
// 1. 按需导入 createApp 函数 import { createApp } from 'vue' // 2. 导入待渲染的 App.vue 组件 import App from './App.vue' / 3. 调用 createApp 函数,创建 SPA 应用的实例 const app = createApp(App) // 4. 调用 mount() 把 App 组件的模板结构,渲染到指定的 el 区域中 app.mount('#app')
组件的基本使用
1. 组件的注册
1.1 注册组件的两种方式
- 被全局注册的组件,可以在全局任何一个组件内使用
- 被局部注册的组件,只能在当前注册的范围内使用
1.2 全局注册组件
app.component('注册标签',导入组件名)
通过component节点 为当前组件注册
1.4 组件注册时名称的大小写
在进行组件的注册时,定义组件注册名称的方式有两种:
2. 组件之间的样式冲突问题
3. 组件的 props
- props 的作用:父组件通过 props 向子组件传递要展示的数据。
- props 的好处:提高了组件的复用性。
可以通过 type 来 定义属性的值类型 。
可以通过 required 选项,将属性设置为 必填项 ,强制用户必须传递属性的值
4. Class 与 Style 绑定
6、自定义事件
在封装组件时,为了让组件的使用者可以监听到组件内状态的变化,此时需要用到组件的自定义事件。
- ① 声明自定义事件
- ② 触发自定义事件
- ③ 监听自定义事件
开发者为自定义组件封装的自定义事件,必须事先在 emits 节点中声明
在 emits 节点下声明的自定义事件,可以通过 this.$emit('自定义事件的名称') 方法进行触发
7、组件上的 v-model
<MyComponent :num="count"></MyComponent>
props :['num']
父组件中
<MyComponent v-model:num="count">
emits: ['update:num'],
子组件中
methods : {
add(){
this.$emit( 'update:num',this.num + 1)
}
}
组件高级 (上)
1、watch 侦听器
// 所有的侦听器,都应该被定义到 watch 节点下
watch: {
// 侦听器本质上是一个函数,要监视哪个数据的变化,就把数据名作为方法名即可
// 新值在前,旧值在后
username(newVal,oldVal) {
console.log(neVal,oldVal)
}
// 如果要侦听的是对象的子属性的变化,则必须包裹一层单引号
'info.username'(newVal) {
console.log(newVal)
}
2、组件的生命周期
组件的生命周期指的是:组件从创建 -> 运行(渲染) -> 销毁的整个过程,强调的是一个时间段。
3、组件之间的数据共享
- 父组件通过 v-bind 属性绑定向子组件共享数据。同时,子组件需要使用 props 接收数据。
- 子组件通过自定义事件的方式向父组件共享数据。
- 父组件在使用子组件期间,可以使用 v-model 指令维护组件内外数据的双向同步:
npm i mitt@2.1.0 -S
import mitt from 'mitt'
const bus = mitt()
export default bus
import bus from './eventBus.js'
data(){return {}count : 0 }
cerated(){
bus.on('countChange',(count) =>{
this.num = count
})
}
import bus from './eventBus.js'
data(){return {}count : 0 }
methods: {
add(){
this.count++
bus.emit('countChange' ,this.count)
}
}
data() {return {color: 'red' } },
provide(){ return{color : this.color } }
子孙节点可以使用 inject 数组,接收父级节点向下共享的数据
inject : ['color']
// 从vue中按需导入 computed 函数
import { computed } from 'vue'
//使用computed 函数 把数据共享包装为响应式
provide(){ return{color : computed( () => this.color ) } }
<h1>子孙组件 {{color.value}}</h1>
4、vue 3.x 中全局配置 axios
import axios from 'axios'
axios.defaults.baseURL = '请求根路径'
app.config.globalProperties.$http = axios
get请求:
methods: {
async getInfo() {
const { data: res } = await this.$http.get('/api/get', {
params: {
name: 'ls',
age: 20,
},
})
console.log(res)
},
}
post请求:
methods: {
async postInfo() {
const { data: res } = await this.$http.post('/api/post', { name: 'zs', age: 20 })
console.log(res)
},
}
组件高级 (下)
1、ref 引用
ref 用来辅助开发者在 不依赖于 jQuery 的情况下 ,获取 DOM 元素或组件的引用。
每个 vue 的组件实例上,都包含一个 $refs 对象 ,里面存储着对应的 DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象 。
<template>
<button @click="showThis">打印 this</button>
</template>
export default {
methods: {
showThis() {
// this 是当前 App 组件的实例对象
console.log(this)
}
}
使用 ref 引用 DOM 元素
<h1 ref="myh1">App 根组件</h1> //加ref属性 起名字
<button @click="showThis">打印 this</button>
export default {
methods: {
showThis() {
// this 是当前 App 组件的实例对象
console.log(this)
this.$refs.myh1.style.color = 'red' //这里的myh1与上面名称对应
}
}
使用 ref 引用组件实例
//子组件
<template>
<div class="left-container">
<h3>Left 组件 --- {{ count }}</h3>
<button @click="count += 1">+1</button>
<button @click="resetCount">重置</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
resetCount() {
this.count = 0
}
}
}
</script>
/父组件中 使用ref属性 为组件添加引用名称
通过this.$refs.引用名称 可以引用组件的实力
<button @click="onReset">重置 Left 组件的 count 值为 0</button>
<Left ref="comLeft"></Left>
methods: {
onReset() {
this.$refs.comLeft.resetCount()
// this.$refs.comLeft.count = 0
}
}
控制文本框和按钮的按需切换
通过布尔值 inputVisible 来控制组件中的文本框与按钮的按需切换
当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法
组件的 $nextTick(cb) 方法,会把 cb 回调 推迟到下一个 DOM 更新周期之后执行 。通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。
<input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef" />
<button v-else @click="showInput">展示输入框</button>
export default {
data() {
return {
// 控制输入框和按钮的按需切换;
// 默认值为 false,表示默认展示按钮,隐藏输入框
inputVisible: false
}
},
methods: {
// 点击按钮,展示输入框
showInput() {
// 1. 切换布尔值,把文本框展示出来
this.inputVisible = true
// 2. 让展示出来的文本框,自动获取焦点 引用this.$nextTick(cb) 方法
this.$nextTick(() => {
this.$refs.iptRef.focus()
})
},
showButton() {
this.inputVisible = false
}
}
2、动态组件
动态组件指的是 动态切换组件的显示与隐藏
实现动态组件渲染
vue 提供了一个内置的 <component> 组件, 专门用来实现动态组件的渲染
<!-- 1. component 标签是 vue 内置的,作用:组件的占位符 -->
<!-- 2. is 属性的值,表示要渲染的组件的名字 -->
<!-- 3. is 属性的值,应该是组件在 components 节点下的注册名称 -->
<button @click="comName = 'Left'">展示 Left</button>
<button @click="comName = 'Right'">展示 Right</button>
<component :is="comName"></component>
data() {
return {
// comName 表示要展示的组件的名字
comName: 'Left'
}
},
当is 指向另外一个组件时原本的组件会被销毁
使用 keep-alive 保持状态
默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组 件的状态。示例代码如下:
<keep-alive><component :is="comName"></component></keep-alive>
keep-alive 会把内部的组件进行缓存,而不是销毁组件
3、插槽
插槽 ( Slot )是 vue 为 组件的封装者 提供的能力。允许开发者在封装组件时,把 不确定的 、 希望由用户指定的 部分 定义为插槽
组件中
<!-- 声明一个插槽区域 -->
<!-- vue 官方规定:每一个 slot 插槽,都要有一个 name 名称 -->
<!-- 如果省略了 slot 的 name 属性,则有一个默认名称叫做 default -->
<slot name="default"></slot>
<Left>
<!-- 默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中 -->
<!-- 1. 如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令 -->
<!-- 2. v-slot: 后面要跟上插槽的名字 -->
<!-- 3. v-slot: 指令不能直接用在元素身上,必须用在 template 标签上 -->
<!-- 4. template 这个标签,它是一个虚拟的标签,只起到包裹性质的作用,但是,不会被渲染为任何实质性的 html 元素 -->
<!-- 5. v-slot: 指令的简写形式是 # -->
<template #default>
<p>这是在 Left 组件的内容区域,声明的 p 标签</p>
</template>
</Left>
没有预留插槽的内容会被丢弃
- 如果在封装组件时 没有预留任何 <slot> 插槽 ,则用户提供的任何 自定义内容 都 会被丢弃
后备内容
- 封装组件时,可以为预留的 <slot> 插槽提供 后备内容 (默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效
具名插槽
- 如果在封装组件时 需要预留多个插槽节点 ,则需要为每个 <slot> 插槽指定 具体的 name 名称 。这种 带有具体 名称的插槽 叫做“具名插槽”。
<slot name="title"></slot>
为具名插槽提供内容
- 在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的 形式提供其名称。
<template #title> <h3>一首诗</h3> </template>
作用域插槽
- 在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种 带有 props 数据的 <slot> 叫做“ 作用 域插槽 ”
<slot name="content" msg="hello vue.js"></slot>
使用 v-slot: 的形式,接收作用域插槽对外提供的数据
作用域插槽对外提供的数据对象,可以使用 解构赋值 简化数据的接收过程
<template #content="scope">
//或者
<template #content="{ msg, user }">
在封装 MyTable 组件的过程中,可以通过作用域插槽把表格每一行的数据传递给组件的使用者
在使用 MyTable 组件时,自定义单元格的渲染方式,并接收作用域插槽对外提供的数据
4、自定义指令
vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。
自定义指令的分类
- 私有自定义指令
- 全局自定义指令
私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:
在使用自定义指令时,需要加上 v- 前缀
directives: {
// 定义名为 focus 的指令,指向一个配置对象
focus: {
// 当指令第一次被绑定到元素上的时候,会立即触发 mounted 函数
// 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
mounted(el) {
el.focus()
}
}
全局自定义指令
全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明
const app = vue.createApp{}
// 定义名为 v-focus 的指令,指向一个配置对象
app.directives: { 'focus', {
// 当指令第一次被绑定到元素上的时候,会立即触发 mounted 函数
// 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
mounted(el) {
el.focus()
}
}
app.directives ( 'focus', (el) => {
el.focus()
})
<h1 v-color="color = 'red'">App 根组件</h1>
app.directives ( 'color',(el,binding) => {
el.style.color = binding.value
})