vue2 vue3 笔记

1. 基本指令

v-bind

操作元素的class列表和内联样式是数据绑定的一个常见需求,所有我们可以使用v-bind处理它们

 1. 绑定class介绍

<!-- 1. 对象语法 -->
<script>
    // 绑定class的两种方式,对象语法,数组语法
    const isActive = true

    const classObj = {
        active: true,
        title: true
    }
</script>
<style>
 .active {
    color:red;
 }
</style>

<div :class="{ 'active': isActive}"></div>

<!-- 也可以多个键值对 -->
<div :class="{active: isActive, title: true}">

<!-- 默认的class和动态class结合 -->
<div class="abc dic" :class="{active: isActive}">

<!-- 将对象放到单独的属性中 -->
<div class='abc cba' :class="classObj">




<!-- 2. 数组语法 -->
<div :class="['abc',title]"></div>
<div :class="['abc',title, isActive ? 'active' :'']"></div>
<div :class="['abc',title, {active: isActive}]"></div>
<script>
    // 绑定class的两种方式,对象语法,数组语法
    const isActive = true

    const classObj = {
         title: 'bcd',
         isActive: true
    }
</script>

2. 绑定 style 介绍

<!-- 1.对象语法 -->
<div :style="{color: finalColor, 'font-size': '30px'}">
<div :style="{color: finalColor, fontSize: '30px'}">
<div :style="{color: finalColor, fontSize: finalFontSize + 'px'}">
<!-- 绑定一个对象 -->
<div :style="finalStyleObj">
<!-- 绑定一个方法 -->
<div :style="getFinalStyleObj()">
return {
    finalColor: 'red',
    finalFontSize: 20,
    finalStyleObj: {
        color: 'red'
    }
}


<!-- 2.数组语法 -->
<div :style="[styleObj, style2Obj]">
return {
    styleObj: {
        color: 'red',
        fontSize: '20px'
    },
    style2Obj: {
        text: '2'
    }
}

 3. v-bind 动态绑定属性名称

<div :[name]="value"></div>
<script>
  return {
    name: 'cba',
    value: 'kobe'
  }
</script>

4. v-bind 属性直接绑定一个对象

<div v-bind="info"></div>
<script>
  const info = {
      name: 'why',
      age: 18,
      height: 1.99
    }
</script>

v-on的修饰符

1. .stop 调用event.stopPropagation() 
2. .prevent 调用 event.preventDefault()
3. .capture 添加事件监听器时使用capture模式
4. .self 只当事件是从监听器绑定的元素本身触发时才会触发回调
5. .{keyAlias} 仅当事件是从特定触发时才会触发回调
6. .once 只触发一次回调
7. .left 只当鼠标左键时触发
8. .right 只当鼠标右键时触发
9. middle 只当鼠标中建时触发
10. passive { passive: true } 模式添加监听器

<!-- 修饰符的使用 -->
<button @click.stop="abx">

v-model

 v-model指令可以在表单 input,textarea以及select元素创建双向绑定
会根据控件类型,自动选取正确的方法来更新元素

// lazy修饰符
1. 默认情况下,v-model在进行双向绑定,绑定的是input事件,那么每次内容输入后,就会将值和绑定的属性进行同步
2. 加上lazy后,那么就会绑定事件切换为change事件,只在提交时触发

// .number
1. 只会截取数字,并存入数字类型

// .trim
1. 会截去字符串前后空格

组件的 v-model

<--父组件-->
<my-input v-modul="modelVlaue"></my-input>
<my-input :modelVlaue="modelVlaue" @update:modelValue='$event'>
	给组件绑定v-model等同于 下面这种写法
</my-input>
    // 绑定多个v-modul
<my-input v-modul="modelVlaue" v-modul:title="title"></my-input>

<script>
	data() {
        return {
            modelVlaue: 'Hello Wrold'
        }
    }
</script>

<--子组件-->
    计算属性方式
<input v-model="value">
    方法实现
<input :value="modelValue" @input="btnClick">
<script>
	props: {
        modelValue: String,
        modelTitle: String,
    },
    emits: ['update:modelValue','update:modulTitle'],
    computed: {
        value: {
            get() {
                retrun this.modelValue
            },
            set(value) {
                this.$emit('update:modelValue',value)
            },
        }
    },
    methods: {
        btnClick(event) {
            this.$emit('update:modelValue',event.target.value)
        }
    }
<script>

v-if v-else v-else-if

1. 只有内容再条件为true才会渲染
2. v-if 是惰性的 为false时,判断的内容完全不会被渲染,会被销毁
3. 当为true时,才会真正渲染条件快中的内容、
4. 因为v-if 是一个指令,必须添加到元素上 此时我们渲染div,但是我们并不希望div这种元素被渲染,我们可以使用 <template>

v-show

1. 和v-if一样
2. 不同的是,当为false时,相当于display:none
3. 不支持template  v-show不能与v-else一起使用

v-for

1. 格式 item in 数组(也可以of)

2. 数组通常来自data或者prop item是取的别名

<!-- item 是每一项 index是索引 -->
<div v-for="(item,index) in data">

<!-- 遍历对象 key是建 -->
<div v-for="(item,key,index) in {name:'red'}">

<!-- 遍历数字 -->
<div v-for="(item,index) in 10">

2. vue2 OptionsApi

computed(计算属性)

1. 对响应式数据的复杂逻辑,应该使用计算属性

2. 计算属性将被混入组件实例中,所有getter和setter的this上下文自动绑定组件实例

3. 计算属性是有缓存的,当多次使用计算属性时,计算属性中的云算只会执行一次

4. 计算属性也是响应式的

computed 和 methods 的区别

computed 是有缓存的 methods没有,每次使用都会执行一次

<!-- 直接当属性使用,不需要加()当函数调用 -->
<div>{{fullName}}</div>

<script>
    const firstName = 'kobe'
    const lastName = 'Bryant'

    computed: {
        fullName() {
            return this.firstName + " " + this.lastName
        }
    }
</script>


<!-- computed的getter和setter方法 -->
<!-- 当写成函数形式时,只执行get方法,当写成对象时,可以配置set方法 -->
<!-- 当调用计算属性时,给计算属性赋值,就会调用set方法 -->
<script>
data() {
    return {
        firstName: 'kobe',
        lastName: 'Bryant'
    }    
}
computed: {
	fullName: {
        get: function() {
            return this.firstName + " " + this.lastName
        },
        set: function(newValue) {
            const names = newVlaue.split(' ')
            this.firstName = names[0]
            this.lastName = names[1]
        }
    }
},
methods:{
    this.fullName = "coder Why"
}
</script>

watch(监听器)

当数据变化时,我们希望在代码逻辑中监听某个数据的变化,就可以使用侦听器watch完成

<script>
data() {
    return {
        question: 'Hello World',
        anwser: '',
        info: { name: 'why', age: 18}
    }
}
methods: {
    queryAnswer(){

    }
},
// 这是跟对象
watch: {
    question(newValue,oldVlaue) {
        // question 是侦听的data中的属性名称
        // newValue 是变化后的新值
        // oldVlaue 是变化前的旧值
        this.queryAnswer()
    },
    // 当需要添加配置时,跟对象
    info: {
        handler: function(newValue,oldVlaue) {
           return console.log(newValue,oldVlaue)
        },
        deep: true, // 深度监听
        immidiate: true // 当页面刷新,立即执行一次
        },
    // 侦听对象里某个属性时
    'info.name': function(newName, oldName) {
        console.log(newName.oldName)
    }
}


// 侦听器的其他用法
created() {
    // 我们可以在created中使用this.$watch来侦听
    // 第一个参数是侦听对象,第二个是回调函数,第三个是配置对象
    const unwatch = this.$watch('info',(newVlaue,oldInfo) => {
        console.log(newValue,oldInfo)
    },{
        deep: true,
        immediate: true
    })
    unwatch() // 当调用时,取消侦听器
}
</script>

组件通信

1. 父组件传递给子组件: 通过props属性

// 什么是Props
 `Props是你在组件上注册一些自定义的attribute
 父组件给这些attribute赋值,子组件通过attribute的名称获取对应的值`

// Props的用法
// 1. 字符串数组,   数组中的字符串就是attribute的名称
 Props: ['title', 'content']

//  2. 对象类型,     对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型,是否必须,默认值等
 Props: {
     title: String,
     content: {
         type: Number, // 类型
         required: true, // 必传
		     default: '123' // 默认值
     }
 }


// 自定义验证函数
propF: {
    validator(value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success','warning'].includes(value)
    }
}

2. 子组件传递给父组件: 通过$emit触发事件

`子组件`
<button @click="addNum">+1</button>

// 1. 先注册事件
emits: ['add','sub']
// 对象写法的目的为了进行参数验证
emits: {
    add: null,
    sub: (num) => {
        if(num>10) {
            return true
        }
        return false
    }
}

// 2. 调用事件
methods: {
    addNum() {
        this.$emit('add')
        this.$emit('sub', 2) // 可以传参
    }
}

// 3. 监听事件
`父组件`
<counter-operation @add="addA" @sub="aubA"/>
methods: {
    addA() {
        // 逻辑处理
    },
    aubA(value) {
        console.log(value)
    }
}

 ​​​​​​3. 非父子组件的通信(子孙组件)

// Provide和Inject 父组件提供,子孙组件使用
// 父组件有一个provide提供数据
// 子组件有个inject选项来开始使用这些数据

`父组件`
export default {
    provide: {
        name: '李晓'
    }
    // 当想使用data里的数据provide需要写成函数
    provide() {
        return {
           name: this.name.length   // 这里的数据不是响应式的,是一次性绑定
           name: computed(() => this.name.length)
        }
    }
}

`子组件`
export default {
    inject: ['name']
}

slot插槽

slot的使用过程就是,抽取共性,预留不同

vue中将 <slot> 元素作为承载分发内容的出口

缩写 #left  v-lost可以写成#

// 组件
<template>
    <div>
      <h2>标题</h2>
	  <slot><i></i></slot> // 可以在slot里定义一个默认元素,没有使用时,就是默认元素
    </div>
</template>


// 使用组件
<my-slot>
	<button>这里的内容就会显示到插槽的位置</button>
</my-slot>



2. 具名插槽
<solt name="my-solt">
// 使用
<my-slot>
    <template v-slot:my-solt> // 使用具名插槽
	<button>这里的内容就会显示到插槽的位置</button>
    <template>
</my-slot>


3. 动态插槽名称
通过v-slot: [dynamicSlotName] 方式动态绑定一个名称
<nav-bar>
	<tempalte v-slot:[name]>
		<button>
		</button>
    </tempalte>
</nav-bar>
data() {
    return {
        name: 'left'
    }
}


3. 作用域插槽
<slot :item="item" :index="index">  // 传递子组件里的数据出去
    // 接收
<template #="slotProps">
<template #:left="slotProps"> // 使用具名插槽
	<button>{{slotProps.item}}</button>
	<i>{{slotProps.index}}</i>
</template #="slotProps">

动态组件

动态组件是使用component组件,通过一个特殊的attribute is 来实现的

<component is="home"></component>

<!-- 动态绑定 -->
<component :is="currentTab"></component>

<!-- 可以向组件里传值,同过porps接收 -->
<component :is="currentTab"
            name='coderwhy'  
           :age="18"
            @pageClick="pageClick">
</component>

<script>
// home的值需要是通过component函数注册的组件或者是在组件内,通过components对象中注册的组件
data() {
    return {
        currentTab: 'home'
    }
}
components: {
    Home,
}
</script>

keep-alive 缓存组件

1. keep-alive 是 Vue的内置组件当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 transition 相似,keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中

2. 在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性

<keep-alive>
    <需要缓存的组件>
</keep-alive>

<!-- keep-alive的属性 当配置keep-alive属性时,要给组件添加name属性,再根据name进行匹配 -->

1. include -string| RegExp | Array 只有名称匹配的组件会被缓存
<keep-alive include='a,b'>
    <需要缓存的组件>
</keep-alive>

<!-- 根据组件的name属性进行匹配 -->
<keep-alive :include="/a,b/">
    <需要缓存的组件>
</keep-alive>

<keep-alive :include="['a','b']">
    <需要缓存的组件>
</keep-alive>

2. exclude -string| RegExp | Array 任何名称匹配的组件都不会被缓存

3. max -number | string . 最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁


<!-- include 和exclude prop 允许组件有条件地缓存 -->
<!-- 二者都可以用逗号分隔字符串,正则表达式或者一个数组表达 -->
<!-- 匹配首先检查组件自身的name选项 -->

异步组件

当需要当前组件时才加载

import {defineAsyncComponent} from 'vue'
1. 函数写法 const AsyncAategory = defineAsyncComponent(() => import('./js/index.js'))


2. 对象写法
const AsyncCategory = defineAcyncCpomonent({
    loader: () => import('./js/index.js')
    loadingComponent: Loading,
    delay: 2000 // 在显示loadingComponent 组件之前,等待多长时间
    onError: function( err, ertry, attempts) {
          // err 错误信息
    	// retry 函数,调用retry尝试重新加载
        // attempts 记录尝试次数
    }
})

$refs

1. 我们在组件中想要直接获取到元素对象或者子组件实例可以使用$refs属性

2. 组件实例有一个$refs属性,它是一个对象,持有注册过 ref attirbute的所有dom元素,和方法实例

<!-- 绑定 -->
<h2 ref="tempalteRef">

<!-- 使用 -->
methods: {
    this.$refs.tempalteRef
}

$parent和$root

1.可以用过$parent来访问父元素
2.可以通过$root来访问根元素
console.log(this.$parent.message)
console.log(this.$root.message)

mixin

组件和组件之间有时候会存在相同的代码逻辑,我们可以对相同代码逻辑进行抽取

1. mixin提供了一种非常灵活的方式,来分发vue组件中的可复用功能
2. mixin对象可以包含任何组件选项
3. 当组件使用mixin对象时,所有mixin对象的选项将被混合进入该组件本身的选项中

mixin的合并规则
情况一:如果是data函数的返回值对象
1.返回值对象默认情况下会进行合并;
2.如果data返回值对象的属性发生了冲突,那么会保留组件自身的数据;

情况二∶如何生命周期钩子函数
1.生命周期的钩子函数会被合并到数组中,都会被调用;

情况三∶值为对象的选项,例如methods、components和 directives,将被合并为同一个对象。
1.比如都有methods选项,并且都定义了方法,那么它们都会生效;
2.但是如果对象的key相同,那么会取组件对象的键值对;
 

// ximin使用   js文件
export const demoMixin = {
    data() {
        return {
            message: 'Hello Wrold'
        }
    },
    methods: {

    },
}


// 导入mixin文件
import {demoMixin} from './mixin.js'
export default {
    mixins: [demoMixin], // demoMixin文件里的数据会混入本组件,成为本组件的一部分
    data() {

    }
}

vue3 CompositionAPI

setup() 的参数与返回值

setup有两个参数
    1.props 父组件传递过来的属性会被放到props对象中,
    2.context 有三个属性
    attrs: 所有的非prop的attribute,
    slots: 父组件传递过来的插槽
    emit: 当我们组件内部需要发出事件时会用到emit

// setup返回值可以在template中被使用,也就是说我们可以通过setup的返回值来替代data选项
import { onMounted, onUpdated, onUnmounted } from 'vue'
export default {
    setup(props, context) {
        // 在 setup 中使用生命周期
        onMounted(() => {
            console.log('onMounted')
            })
        onUpdated(() => {
            console.log('onUpdated')
            })
        onUnmounted(() => {
            console.log('onUnmounted')
            })
        console.log(props.message)
        console.log(context.attrs)
        console.log(context.slots)
        console.log(context.emit)
        return {
            title: 'Hello World'
        }
    }
}

Reactive

当我们使用reactive函数处理我们的数据之后,数据再次使用时会进行依赖收集
当数据发生改变时,所有收集到依赖都是进行对应的相应式操作,
对传入的类型是有限制的,必须是一个对象或者数组类型

import {reactive} from 'vue'
setup() {
    const state = reactive({
    name: 'coderwhy',
    counter: 100
    })
	return {
        state
    }
}

Reactive 的判断 api

1.isproxy 检查对象是否由reactive或者readonly创建的proxy

2.isReactive 检查对象是否是由reactive创建的响应式代理
如果该代理是reactive建的,包裹了由reactive创建的另一个代理,它会返回true

3.isReadonly 检查对象是否是由readonly创建的只读代理

4. toRaw 返回reactive或readonly代理的原始对象

5.shallowReactive 创建一个响应式代理,它之跟踪自身property的响应式,但不执行嵌套对象的深层响应式转换

6.shallowReadonly 创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深层只读转换(深层还是可读可写的)

Ref

ref会返回一个可变的响应式对象,该对象作为一个响应式的引用维护了它内部的值,内部的值是在ref的value属性中被维护

在template模板中使用ref对象会自动解包,只能是浅层解包,

但是在setup函数内部,它依然是一个ref引用,要使用ref.value的方式

<button @click='increment'>{{state}}</button> 
import {ref} from 'vue'
setup() {
    let state = ref(100)
     const increment = () => {
        state.value++
        console.log(state.value)
    }
    return {
        state,
        increment
    }

}


// 拿元素ref属性
<h2 ref="title">
import { ref, watchEffect } from 'vue'
setup() {
    const title = ref(null)
    watchEffect(() => {
        console.log(title.value)
    })
    return {
        title
    }
}

Ref的其他 api

toRefs

toRefs函数,可以将reactive返回的对象中的属性都转成ref

import {toRefs} from 'vue'
const state = reactive({
    name:'why',
    age:19
})
const {name, age } = toRefs(state)
// 相当于在state.name和ref.value之间建立了链接,任何一个修改都会引起另外一个变化


1. toRef // 只建立对象中的单个属性
import {toRef} from 'vue'
const state = reactive({
    name:'why',
    age:19
})
let name = toRef(state,'name')

unref

如果我们想要获取一个ref引用中的value,那么可以通过unref方法

如果参数是一个ref,则返回内部值,否则返回参数本身
这是 val = isRef(val) ? val.value: val 的语法糖函数

isRef

判断值是否是一个ref对象

shallowRef

创建一个浅层的ref对象

import {shallowRef} from 'vue'
setup() {

    const info = shallowRef({name: 'why'})

    return {
        info
    }
}

triggerRef

手动触发和shallowRef相关的副作用

import { ref, triggerRef } from 'vue'
setup() {
    const info = ref({name: 'why'})
    const changeInfo = () => {
        info.value.name = 'james'
        triggerRef(info)
    }
    return {
        info
    }
}

customRef

自定义ref,并对其依赖项跟踪和跟新触发,进行显示控制

需要一个工厂函数,该函数接受track 和 trigger 函数作为参数 并且应该返回一个带有get和set的对象

readonly

响应式对象不希望在别的地方修改,可以使用readonly

readonly 方法会传入三个类型的参数

1. 普通类型
2. reactive返回的对象
3. ref对象

import {readonly} from 'vue'
setup() {
    const info = {
        name: 'why'
    }
    const infoonly = readonly(info)
    return {
        infoonly
    }
}

computed(计算属性)

// 计算属性
import { ref, computed } from 'vue'
setup() {
    const firstName = ref('kobe')
    const lastName = ref('Bryant')

    // 函数写法
    const fullName = computed(() => firstName.value+lastName.value)

    // 对象写法
    const fullName = computed({
        get: ()=> firstName.value+lastName.value,
        set: (value) => {}
    })
    return {
        firstName,
        lastName
    }
}

watch 和 watchEffect

watchEffect

用于自动收集响应式数据的依赖

默认执行一次,只相应用到的依赖

import { ref, watchEffcect } from 'vue'
setup() {
    const name = ref("why")
    const age = ref(18)
    watchEffect(() => { // 默认执行一次,只相应用到的依赖
        console.log('name',name.value)
    })
    const stop = watchEffect(() => {
        console.log('age': age.value)
    })
    const stop = watchEffect((aaa) => {
        aaa(() => {
            // 可以在这个函数中清除额外的副作用
            request.cancel()
        })
        console.log('age': age.value)
    })
    const changeAge = () => {
        age.value++
        if(age.value>25){
            stop() // 调用后,就不再侦听了
        }
    }
}

watch

1. watch 需要手动指定侦听的数据源,并在回调函数中执行副作用
2. 只有当被侦听的源发生变化时才会执行回调
3. 第一次不会直接执行
4. 访问侦听状态变化前后的值

import { reactive, watch } from 'vue'
// 侦听单个数据源
setup() {
    const info = reactive({name: 'why', age: 18})
    `1. 侦听watch时,传入一个getter函数`
    watch(() => info.name, (newValue, oldValue) => {
        consloe.log('新:'newVlaue "旧"oldValue)
    })

    `2. 传入可响应对象,reactive对象/ref对象`
    '情况一: reactive对象获取到的newvalue和oldvalue本身都是reactive对象'
    watch(info,(newValue, oldValue) => {
        consloe.log('新:'newVlaue "旧"oldValue)
    })

    '情况二: ref对象获取newvalue和oldvalue是value值本省'
    const name = ref('why')
    watch(name,(newValue, oldValue) => {
        consloe.log('新:'newVlaue "旧"oldValue)
    })

    '如果希望newvalue和oldvalue是一个普通对象'
    watch(()=> {
        return {...info}
    },(newValue, oldValue) => {
        consloe.log('新:'newVlaue "旧"oldValue)
    })
    return {

    }
}





// 侦听多个数据源
setup() {
    const info = reactive({name: 'why',age: 18})
    const name = ref('why')
    watch([info,name],([newValue, oldValue],[newValue, oldValue])=> {
        consloe.log('新:'newVlaue "旧"oldValue)
    },{
        deep: true  // 深度监听,直接监听reactive对象时是默认就是为true
        immediate: true // 默认执行一次
    })
    return {

    }
}

provide inject

无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。

// 给子孙组件传值
<home/>
import {provide } from 'vue'
import Home from './Home.vue'
setup(){
    const name = 'whty'
    provide('name',name)
}

// 子孙组件
import {inject} from 'vue'
setup() {
    const name = inject('name','提供默认值')
    return {
        name
    }
}

render 函数(渲染函数)

export default {
    render() {
        return h()  // h() 函数是用于创建vnode的一个函数
        return h()  // 接收三个参数
1.{string|object|function} 一个html标签,一个组件,一个异步组件或者一个函数式组件
'div' // 必须的

2. {object} props 与attribute,prop 事件相应的对象,我们会在模板中使用
{} // 可选的

3. {string|array|object|children} 子vnodes 使用`h()`构建,或者字符串获取文本vnode或者有插槽的对象

['some text comes first', h('h1', 'A headline'), h(MyComponent, {someProp: 'foobar'})]
    }
}



// 例子
import { h } from 'vue'
export default {
    render() {
        return h('div', {class: 'app'}, [
        h('h2', null, `当前计数: ${this.counter}`),
        h('button', {
            onClick: () => this.counter++
        }, '+1')
        h('button', {
            onClick: () => this.counter--
        }, '-1')
        ])
    }
}

自定义指令

1、指令的生命周期
created: 在绑定元素attribute或者事件监听器被应用之前调用
beforMount: 当指令第一次绑定到元素并且在挂载父组件之前调用
mounted:在绑定元素的父组件被挂载后调用;
beforeUpdate :在更新包含组件的 VNode之前调用;
updated:在包含组件的VNode 及其子组件的VNode更新后调用;beforeUnmount:在卸载绑定元素的父组件之前调用;
unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;

// 在某些情况下,你需要对DOM进行底层操作时,就会用到自定义指令


direactives: {
    focus: {
        mounted(el, bindings, vnode ,preVnode) {
            console.log('focus mounted')
            el.focus()
        }
    }
}

nexttick

将回调推迟到下一个dom更新周期之后执行,在更改一些数据等待dom更新后立即使用它

import {nextTick} from 'vue'
setup() {
    nexttick(() => {
      // 更新dom后操作
   })
}

router 配置

const routes = [
    {
        path: '/',
        redirect: '/home'  // 重定向
    },
    {
        path: '/home',
        name: 'home', // 路由唯一的名字
                                  // 魔法注释,分包操作
        components: () => import(/* webpackChunName: 'home-chunk'*/'./home'), // 路由懒加载
        meta: { name: 'why', age: 18 } // 原数据
    	quilren:[
           {
            path: 'message'  // 嵌套路由
            }
         ]
    },
    {
        path: '/why/:name' // 动态路由     $route.params.name可以拿动态路由的值
            `vue3` import { useRoute } from 'vue-router'
                   setup() {
                       const route = useRoute()
                       route.params.name
                   }
    },
    {
        path: '/:pathMatch(.*)' // 任意匹配
        component: () => import('./NotFound.vue')
    }
]



`编程式导航`
this.$router.push()
this.$router.push({path:'',query:{}})
this.$router.push({name:'',params: {}})

import { useRouter } from 'vue-router'
setup() {
    const router = useRouter()
    const click = () => {
        router.push('/')
    }
    return {
        click
    }
}

动态添加路由

`动态添加路由`
const caregoryRoute = {
    path: '/category',
    component: () => import('./')
}
// 添加顶级路由对象
router.addRoute(caregoryRoute)
// 添加二级路由对象
router.addRoute('home', {
    path: 'moment',
    component: () => import('')
})


`动态删除路由`
1.添加一个name相同的路由
route.addRoute({path:'/a',name: 'a'})
route.addRoute({path:'/b',name: 'a'})
2.通过removeRoute方法,传入路由名称
route.removeRoute('/a')
3.通过addRoute方法的返回值回调
const removeRoute = route.addRoute(reoteRecord)
removeRoute()



router.hasRoute() // 查询路由是否存在
router.getRoutes() // 获取一个包含所有路由记录的数组

路由导航守卫

`前置导航守卫`
router.beforEach((to,from,`next`) => {
    // next vue-router4已经不使用了
    // to 即将跳转到的route对象
    // from 从那个route对象来的
    // 进行了一次路由跳转
    return false
    // 返回值问题
    1. false 不进行导航
    2. undefined 或者不写返回值,进行默认导航
    3. 字符串 '/login'
    4. 对象: 类似于 router.push({path: '',query: {}})
})

`后置导航守卫`
router.afterEach((to,home) => {
	// 在路由跳转之后,再回调
})

vuex

vuex应用的核心就是store(仓库)
vuex的状态存储是响应式的
不能在组件内直接修改store中的状态,需要提交(commit)mutation

import { createStore } from 'vuex'
const store = createStore({
  namespaced: true // 使用modules开启命名空间
  state() { // 数据管理
      return {
          counte: 1
      }
  },

  // 某些属性我们需要经过变化后使用,可以使用getters
  getters: {
      current(state,getters) {
          // 参数一 state对象
          // 参数二 getters 对象
          return function(n) { // 返回函数写法
              return 3
          }
      }
  }      `使用$store.getters.方法名`

  // 更改vuex的store中的状态的唯一方法就是提交mutation
  mutations: {
       increment(state,paload) {
            // 参数一state对象
            // 参数二调用传递的参数
       }
       `使用$store.commit('increment', {name: '男'})`
  }
  // actions 可以包含任意异步操作, 提交的是mutarion 而不是直接变更状态
  actions: {
      getHomeMultiDate(context,payload) {
          context.commite('addBannerData',{age:18})
      }
      `使用this.$store.dispatch('getHomeMultiDate',{name: 'age'})`
  }
  // 讲store分割成模块
  import { a, b } from './a'
  modules: {
      a: moduleA,
      b: moduleB
      `使用$store.state.a`
  }
})
export default store

`vue2组件中使用`
import { mapState, mapGetters, mapMtations, mapActions } from 'vuex'
methods: {
    ...mapMutations(['increment'],{name: '男'})
    ...mapActions(['getHomeMultiDate'])
},
computed: {
    fullName() {
        return this.$store.state.counte
    }
    // 数组写法
    ...mapState(['counte'])
    ...mapGetters(['current'])
    // 对象写法
    ...mapState({
        Scounte: state => state.counte
    })
    ...mapGetters({
        current: 'current'
    })

}

`vue3中使用`
import { mapState, useStore, mapGetters,mapMtations, mapActions } from 'vuex'
import { computed } from 'vue'
setup() {
    // 第一种方式
        const store = useStore() // 拿到store对象
        const sCounter = computed(() => store.state.counter)
        // 第二种方式(可以封装)
        const storeStateFns = mapState(['age', 'name'])
        // 同理
        const storemapGettersFns = mapGetters(['age', 'name'])
        const storeState = {}
        Object.keys(storeStateFns).forEach(fnKey => {
            const fn = storeState[fnKey].bind({$store: store}) // 绑定this
            storeState[fnKey] = computed(fn)
        })


        const storeMutations = mapMtations(['increment'])
        const storeMapActions = mapActions(['increment'])
    return {
        sCounter
     ...storeState
     ...storeMutations
     ...storeMapActions
    }
}

vue3 注册全局实例属性或方法,在 setup 中使用

const app = createApp({})
app.config.globalProperties.$axios = () => {}

// setup中使用
import { getCurrentInstance } from 'vue'
;`getCurrentInstance这个函数来返回当前组件的实例对象,也就是当前vue这个实例对象`
//vue3的setup函数中的this为undefined,需要使用组合API提供的getCurrentInstance()函数,通过appContext.config.globalProperties来调用根实例上挂载的方法。
// tips:另外如果想获取当前组件实例,通过getCurrentInstance下的proxy实现,proxy支持开发环境、生产环境,而ctx只支持开发环境,打包后结构不一样

const instance = getCurrentInstance()
console.log(instance.appContext.config.globalProperties) // 打印可以看到当前组件上挂载了的方法
instance.appContext.config.globalProperties.$axios() // 使用axios

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

派大星965

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值