一.jsconfig.json文件
1.1. jsconfig.json文件的作用
作用:给vsocde来进行读取,VsCode在读取到其中的内容时,给我们的代码更有好的提示。
vue.config.js配置别名
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({//defineConfig定义配置文件
transpileDependencies: true,
// 配置webpack
configureWebpack:{
resolve:{
// 配置路径别名
// @已经配置好的路径别名,对应src的路径
alias:{
"utils":"@/utils"
}
}
}
})
jsconnfig.json 例如:让vscode识别utils,从而有更友好的代码提示。
{
"compilerOptions": {
"target": "es5",//目标打包成es5的代码
"module": "esnext",//使用模块化的时候,使用es的模块化
"baseUrl": "./",//决定路径的src相当于当前目录
"moduleResolution": "node",//模块的查找顺序按照node的顺序进行查找
"paths": {
"@/*": [
"src/*"
],
//配置utils
" utils/*":[
"src/utils/*"
]
},
"lib": [//可能会用的库
"esnext",
"dom",
"dom.iterable",//使用可迭代对象有更有好的方法提示
"scripthost"//提供更友好的数组环境
]
}
}
1.2. vue不同版本的作用
- 默认Vue版本 runtime: 运行时,vue-loader完成template的编译过程。
- vue.esm-bundler: runtime + compile: 运行+编译,d对template进行编译。
tempalte模板-->createVNode()(v3:createElementBlock())-->VNnode-->虚拟dom-->真实DOM
1.3. css的scoped作用域
scoped属性让CSS只对当前组件中的元素起作用,防止了CSS全局污染。 设置scoped作用域,相当于添加了一个属性:"data-v-7ba5bd90"
1.4. npm init vue@latest创建项目
- 执行命令会首先安装一个本地工具:create-vue
- 使用create-vue创建一个vue项目
- 底层基于vite打包
Need to install the following packages:
create-vue@3.6.1
Ok to proceed? (y) y
Vue.js - The Progressive JavaScript Framework
√ Project name: ... 03-project-vite
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
二. 组件间的通信
2.1. 组件的嵌套关系
- 父组件/子组件
- 父组件传递给子组件:通过props属性;
- 子组件传递给父组件:通过$emit触发事件;
2.2. 父传子 - props(重要)
1.什么是Props呢?
- Props是你可以在组件上注册一些自定义的attribute;
- 父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值;
2.Props有两种常见的用法:
- 方式一:字符串数组,数组中的字符串就是attribute的名称;
- 数组语法的弊端:1.不能对类型进行验证。2.没有默认值
父组件: <show-info name="www" age="18" height="1.8"> </show-info>
子组件中: props: ["name", "age", "height"]
- 方式二:对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默认值等等;
- 那么type的类型都可以是哪些呢?
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
// 对象语法
父组件: <show-info name="www" age="18" height="1.8"> </show-info>
//需要加 " :"age="39",使其变成js代码,里面的30就变成一个数字
<show-info name="kobe" :age="39" :height="1.99"> </show-info>
<show-info></show-info>
子组件: props: {
name: {
type: String,
default: "我是默认的name"
},
age: {
type: Number,
default: "12"
},
height: {
type: Number,
default: 0,
},
}
父组件:
<template>
<div class="app">
<!-- 1.展示why信息 -->
<show-info name="www" age="18" height="1.8"> </show-info>
<show-info name="kobe" age="39" height="1.99"> </show-info>
</div>
</template>
<script>
import ShowInfo from "./ShowInfo.vue"
export default {
components: {
ShowInfo
}
}
</script>
<style scoped></style>
子组件:
<template>
<div class="showinfo">
<div class="info">
<h2>性别:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>身高:{{ height }}</h2>
</div>
</div>
</template>
<script>
export default {
// 作用接收父组件传递过来的属性
//数组语法
props: ["name", "age", "height"]
}
</script>
<style scoped></style>
3.对象类型的其他写法
2.3. 非prop的attribute
1.什么是非Prop的Attribute呢?
- 当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的Attribute;
- 常见的包括class、style、id属性等;
- Attribute继承
- 当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中:
2.4. 子传父 - $emit(重要)
1.什么情况下子组件需要传递内容到父组件呢?
- 当子组件有一些事件发生的时候,比如在组件中发生了点击,父组件需要切换内容;
- 子组件有一些内容想要传递给父组件的时候;
- 我们如何完成上面的操作呢?
- 首先,我们需要在子组件中定义好在某些情况下触发的事件名称;
- 其次,在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中;
- 最后,在子组件中发生某个事件的时候,根据事件名称触发对应的事件;
3.我们封装一个AddCounter.vue的组件:
- 内部其实是监听两个按钮的点击,点击之后通过 this.$emit的方式发出去事件;
子组件
<template>
<div class="add">
<button @click="btnClick(1)">+1</button>
<button @click="btnClick(5)">+5</button>
<button @click="btnClick(10)">+10</button>
</div>
</template>
<script>
export default {
methods: {
btnClick(count) {
console.log("click");
// 让子组件发出自定义事件,
// 第一个参数add名字可以自定义。
// 第二个参数是传递的参数
this.$emit("add",count)
}
}
}
</script>
<style scoped></style>
父组件
<template>
<div class="app">
<h2>当前计数:{{ counter }}</h2>
<!-- v-on: (@) 监听组件内部的事件 -->
<!--1. 自定义,add-counter,并且监听内部事件 -->
<add-counter v-on:add="addBtnClick"></add-counter>
<sub-counter></sub-counter>
</div>
</template>
<script>
import AddCounter from './AddCounter.vue'
import SubCounter from './SubCounter.vue'
export default {
data() {
return {
counter: 0,
}
},
components: {
AddCounter,
SubCounter
},
methods: {
addBtnClick(count) {
this.counter += count
}
}
}
</script>
<style scoped></style>
三. 组件的插槽Slot
3.1. 认识Slot的作用
1.来定义插槽slot
- 插槽的使用过程其实是抽取共性、预留不同;
- 我们会将共同的元素、内容依然在组件内进行封装;
- 同时会将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素;
2.如何使用slot呢?
- Vue中将 元素作为承载分发内容的出口;
- 在封装组件中,使用特殊的元素就可以为封装组件开启一个插槽;
- 该插槽插入什么内容取决于父组件如何使用;
3.2. Slot的基本使用和默认值(重要)
1.子组件
<template>
<div>
<h2> show-message</h2>
<slot>
<h2>我是默认的内容</h2>
</slot>
</div>
</template>
2.父组件
<template>
<div class="app">
<div class="content">
<show-message>
<button>使用插槽</button>
</show-message>
</div>
</div>
</template>
3.3. Slot的具名插槽(重要)
1.具名插槽使用的时候缩写:
- 跟 v-on 和 v-bind 一样,v-slot 也有缩写;
- 即把参数之前的所有内容
(v-slot:)
替换为字符#
; 默认情况:
<nav-bar>
<template v-slot:left>
<button>返回</button>
</template>
<template #center>
<button>内容</button>
</template>
<template #right>
<button>登录</button>
</template>
</nav-bar>
1.子组件
<div class="nav-bar">
<div class="left">
<slot name="left">left</slot>
</div>
<div class="center">
<slot name="center">center</slot>
</div>
<div class="right">
<slot name="right">right</slot>
</div>
</div>
2.父组件中
<template>
<div class="app">
<nav-bar>
//在template中写上对应的名字
<template v-slot:left>
<button>返回</button>
</template>
<template v-slot:center>
<button>内容</button>
</template>
<template v-slot:right>
<button>登录</button>
</template>
</nav-bar>
</div>
</template>
使用插槽后
3.4. 动态插槽名
1.什么是动态插槽名呢?
- 目前我们使用的插槽名称都是固定的; 比如 v-slot:left、v-slot:center等等;
- 我们可以通过 v-slot:[dynamicSlotName]方式动态绑定一个名称
<nav-bar>
<!-- v-slot:[]动态插槽,引入变量 -->
<template v-slot:[position]>
<a href="">注册</a>
</template>
</nav-bar>
<button @click="position = 'left'">按钮</button>
<button @click="position = 'center'">按钮</button>
<button @click="position = 'right'">按钮</button>
data() {
return {
position: "center",
}
},
3.5. Vue编译作用域
1.渲染作用域
在Vue中有渲染作用域的概念:
- 父级模板里的所有内容都是在父级作用域中编译的;
- 子模板里的所有内容都是在子作用域中编译的;
3.6. 作用域插槽使用
- 核心: 将子组件中的数据传递给父组件的插槽来使用