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)
})
posted @   小白咚  阅读(224)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示