vue3笔记
#### 代码片段
网址:http://snippet-generator.app/
create vue app
vueapp
用户代码片段--html.json
`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
}
},
methods: {
},
template: `
<div>
</div>`
});
const vm = app.mount('#app');
</script>
</html>
`
---"prefix": "vueapp"前缀
`{
"create vue app": {
"prefix": "vueapp",
"body": [
"<!DOCTYPE html>",
"<html lang=\"en\">",
"<head>",
" <meta charset=\"UTF-8\">",
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">",
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
" <title>Document</title>",
" <style>",
" ",
" </style>",
" <script src=\"https://unpkg.com/vue@next\"></script>",
"</head>",
"<body>",
" <div id=\"app\"></div>",
"</body>",
"<script>",
" const app = Vue.createApp({",
" data() {",
" return {",
"",
" }",
" },",
" methods: {",
"",
" },",
" template: `",
" <div>",
"",
" </div>`",
" });",
"",
" const vm = app.mount('#app');",
"</script>",
"</html>"
],
"description": "create vue app"
}
}`
#### 指令
---不常用---
v-once
v-text
v-html
v-pre
v-cloak
[v-cloak] {
display: none
}
---常用指令---
v-bind
:class="{active: isActive,title: true}"
:class="{方法()}"
:class="{变量}"
:class="['abc', title, 三元运算, {active: isActive}]"
:style="{color: finalColor, 'font-size': '30px', fonstSize: '30px',fontSize: 变量 + 'px'}"
:style="[{},{},对象变量]"
<div v-bind="info"> // 分别绑定<div :name="" :age="" :height="">
info: {
name: '',
age: 0,
height: 1.88
}
区别于:<div :info="info">
v-on
修饰符:
.stop - 调用event.stopPropageation() // 停止冒泡
.prevent - 调用event.preventDefault()
.capture - 添加事件侦听器时使用capture模式
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调
.{keyAlias} - 仅当事件是从特定键触发时才触发回调
.once - 只触发一次回调
.left - 只当点击鼠标左键时触发
.right - 只当点击鼠标右键时触发
.middle - 只当鼠标中键时触发
.passive - { passive:true } 模式添加侦听器
绑定两个事件
<div v-on="{click: btnClick, mousemove: mouseMove}">
获取事件对象$event
<button @click="btnClick($event, 'coderwhy')">
btnClick(event, name){
}
----条件渲染---
v-if
v-else
v-else-if
v-show
<template v-if> 不会显示在节点
v-show不支持<template>
v-show不可以和v-else一起使用
----列表渲染----
v-for
可遍历数组,对象,数字
----数组更新检测----
push
pop
shift
unshift
splice
sort
reverse
----计算属性----
computed有缓存
----侦听器watch---
vue3弃用
watch: {
"info.name": function(newValue, oldValue) {
// 只针对name属性改变监听
}
}
created(){
this.$watch("info",(newValue,oldValue){
}, deep:true,immediate:true)
}
deep深度监听复杂对象
oldvalue和newvalue时相同的
因为指向的是一个地址
监听复杂数组[{},{}]
不推荐用deep
使用组件接收对象,props
-----浅拷贝和深拷贝-----
const test = Object.assign({}, info); //浅拷贝(最外层的不会干扰,内部的对象还是指向原来的地址)
const test = JSON.parse(JSON.stringfy(info)); //深拷贝
#### webpack打包工具
npm install webpack webpack-cli -g -g全局安装, -D局部安装
webpack --version
#### 局部安装
npm init -y
npm install webpack webpack-cli
#### 全局安装脚手架
npm install @vue/cli -g
vue create 项目名称
Manally手动选择特性
Choose,Babel,
vue3
in dedic
n不保存预设
#### 项目文件
.browerslisttrc
兼容哪些浏览器
#### vite安装
1. npm init @vitejs/app
2. npm install @vitejs/create-app -g
create-app
框架vue
vue-ts
npm install
#### 组件化
创建项目(webpack)
#### vscode提示插件
volar
vetur
vue3 Snippets
自动生成vue模板
vue
#### 引入组件
import Header from "./Header.vue"; //
建议加上.vue后缀名
有提示,可跳转
### css的作用域
#### 通信
props指定多个类型
propsdemo: [String, Number]
默认对象:
default() {
return { message: 'hello' }
}
不然会影响其他组件的使用;
不想让子组件继承父组件的属性
inheritAttrs: false
获取父组件的样式
父:<div class="why">
子:<div :class="$attrs.class"> 也可全部继承<div v-bind="$attrs">
----------------------
子组件声明:
emit: ['add', 'sub']
emit: {
add: null,
addN: (num, name, age) => { // 自定义事件传递方式
if(num > 10) { // 参数验证
return true
}
return false; // 参数也会传过去,但是会报警告
}
}
使用:
this.$emit('addN', this.name,this.num,...)
父组件:
<div @add="addOne" @addN="addNum">
#### 点击事件
<div class="demo" :class={active: clickIndex === index}>
.demo.active {
color: red;
}
#### 非父子组件共享数据-vue2和3都能用,但是平时很少用,用vuex
孙子组件接收爷爷组件的数据
父组件有一个provide选项来提供数据;
子组件有一个inject选项来使用这些数据;
主页面App.vue
provide: {
name: 'why',
age: 18
}
或者(this指向函数,引用data里边的数据)
provide() {
return {
name: 'why',
lengthName: this.name.length // 一次性赋值,这个name变量再改变,不会重新赋值;
}
}
data() {
return {
name: ["11"]
}
}
孙子页面:
inject: ['name','age'] // 注入
---让子组件监听到变化---变成响应式的
App.vue
import { computed } from 'vue';
provide() {
return {
lengthName: computed(() => this.name.length)
}
}
子组件
(因为计算属性返回的式一个ref对象,所以要value)
{{lengthName.value}}
inject: ['lengthName']
#### 兄弟组件之间通信
全局事件总线mitt库
eventBus
1. vue3从实例中移除了$on,$off,$once的方法,所以我们希望继续使用全局使事件总线,
要通过第三方的库;
2. vue3官方有推荐的一些库,例如mitt,tiny-emitter;
3. npm install mitt
4. 分装evnetbus.js文件
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
兄弟一:
imoprt emitter from './eventbus.js'
发送事件:
emitter.emit("why", {name: "why", age: 18})
兄弟二:监听
imoprt emitter from './eventbus.js'
created() {
emitter.on("why", (info) => {
console.log(info)
})
}
监听所有事件:
emitter.on("*", (type, info) => {
console.log('事件类型',type);
console.log('参数',info)
})
取消emitter中所有的监听
emitter.all.clear();
取消某一个
function onFoo() {}
emitter.on('foo',onFoo);
emitter.off('foo', onFoo)
#### 插槽slot
<div>
<slot></slot>
</div>
----具名插槽----分配各个部分的内容
NavBar.vue
<div class="left">
<slot name="left"></slot>
</div>
<div class="center">
<slot name="center"></slot>
</div>
<div class="right">
<slot name="right"></slot>
</div>
使用:
app.vue
<nav-bar>
<template v-slot:left>
<button>左边的按钮</button>
</template>
<template v-slot:center>
<button>搜索框</button>
</template>
<template v-slot:right>
<button>右边的按钮</button>
</template>
</nav-bar>
-----自定义插槽-----
定义组件:
<div>
<slot :name="name"></slot>
</div>
props: {
name: String
}
使用:
data() {
return {
name: "why"
}
}
<nav-bar :name="name">
<template v-slot:[name]>
<i>内容</i>
</template>
</van-bar>
-----注意---
v-slot:可以换成#
<template #插槽名>
-----作用域插槽-----
父组件访问插槽子组件变量:
子组件插槽ShowNavList
<template v-for="(item, index) in names" :key="item">
<slot :item="item" :index="index"></slot>
</template>
props: {
names: {
type:Array,
defalut: () => []
}
}
父组件使用:
<show-nav-list :names="name">
<template v-slot="slotProps">
<button>{{slotProps.item}}-{{slotProps.index}}</button>
</template>
</show-nav-list>
data() {
return {
name: ['123']
}
}
#### 动态组件的使用
1. 通过v-if判断来实现(不推荐)
2. 动态组件(推荐)
动态组件是使用component组件
通过一个特殊的attribute is 来实现
<component :is="currentTab"></component>
这个currentTab的值需要是什么内容呢?
可以是通过component函数注册的组件(全局,vue.component())
在一个组件对象的components对象中注册的组件;
data() {
return {
currentTab: 'Home'
}
}
components: {
Home,
About,
}
绑定事件和参数(每个组件根据不同的参数事件,不同监听就可以了)
<component :is="currentTab"
name="codewhy"
:age="18"
@pageClick="paheClick"></component>
-----防止切换组件,旧组件状态被销毁----
作用:
我们再切换组件后,about组件会被销毁掉,再次回来时会重新创建组件,
但是,我们想继续保持组件的状态,而不是销毁掉,
使用一个内置组件keep-alive
<keep-alive>
<component :is="currentTab"
name="codewhy"
:age="18"
@pageClick="paheClick">
</component>
</keep-alive>
属性:
include -string|RegExp|Array 只有名称匹配的组件会被缓存
exclude -string|RegExp|Array 任何名称匹配的组件都不会被缓存
max -number|string 最多可以缓存的多少个组件实例,一旦达到这个数字,
那么缓存组件中华最近没有被访问到的实例会被销毁
<!-- 逗号分隔字符串 ,不用加:-->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- regex (使用'v-bind') -->
<keep-alive :include="/a|b/">
<component :is="view">
</component>
</keep-alive>
<!-- Array (使用'v-bind') -->
<keep-alive :include="['a', 'b']">
<component :is="view">
</component>
</keep-alive>
#### 异步组件的使用
#### Webpack的代码分包
1. 默认的打包过程
默认的情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,
那么webpack在打包时就会将组件模块打包到一起(比如一个app.js中)
这个时候随着项目的不断庞大,app.js文件的内容过大,会造成首屏的渲染速度变慢
例如引入一个文件
math.js
export function sum(a,b) {
retuen a+b
}
1. import { sum } from './utils/math'
// 通过import函数导入的模块,后续webpack对其进行打包的时候就会进行分包的操作
2. import('./utils/math').then((res) => {
res.sum(20, 30)
})
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?