vue3知识记录-基础篇

121 阅读1分钟

热身

模板标签的基本使用

<script setup>
    import {ref} from 'vue';
    const msg=ref('你好,vue3')
</script>
<template>
    <span>{{msg}}</span>
</template>

简单

生命周期钩子

<script setup>
    import {onMounted,onUnmounted,ref} from 'vue';
    const count=ref(1)
    const timter=ref('')
    onMounted(()=>{
        timer.value=setInterval(()=>{
            count.value++
        },1000)
    })
    onUnmounted(()=>{
        clearInterval(timer.value)
    })
</script>
<template>
</template

下一次dom刷新



<template>
    <div>
        <div ref="myParagraph" @click="changeMsg">
            {{ msg }}
        </div>
    </div>
    
</template>
<script setup lang="ts">
import {ref,nextTick} from 'vue';
const myParagraph = ref<HTMLDivElement|null>(null)
const msg=ref('你好!vue')
const changeMsg=()=>{
    msg.value="努力学习的仔仔"
    nextTick(()=>{
        console.log(myParagraph.value?.textContent)
    })
}
</script>

<style lang="scss" scoped>

</style>

插槽用法 默认插槽和具名插槽

//父
<script setup>
import {ref} from 'vue';
import Child from './components/Child.vue'
const msg=ref('hello')
</script>
<template>
<Child>
    <span>{{msg}}</span>
    <template #header>
      <h2>这是头部内容</h2>
    </template>
    <template #footer>
      <h2>这是低部内容</h2>
    </template>
</Child>
</template>

//子
<script setup>

</script>
<template>
<slot></slot>
<slot name="header"></slot>
<slot name="footer"></slot>
</template>

动态css(style中绑定变量)

<script setup>
import {ref,onMounted} from 'vue';
const myColor=ref('red')
const colorList=['red','blue','green']
onMounted(()=>{
    setInterval(()=>{
        myColor.value=colorList[Math.floor(Math.random()*3)]
    },1000)
})
</script>
<template>
<p>我是p标签</p>
</template>
<style scoped>
p{
color: v-bind('myColor')
}
</style>

ref全家桶使用(ref、Ref、toRef、toRefs、isRef、unRef)

<script setup lang="ts">
import { ref, Ref, reactive,isRef, toRef } from "vue"

const initial = ref(10)
const count = ref(0)

// 挑战 1: 更新 ref
function update(value:number) {
    // 实现...
    count.value=value
}

/**
 * 挑战 2: 检查`count`是否为一个 ref 对象
 * 确保以下输出为1
*/
console.log(
    isRef(count)?1:0
    // impl ? 1 : 0
)

/**
 * 挑战 3: 如果参数是一个 ref,则返回内部值,否则返回参数本身
 * 确保以下输出为true
*/
function initialCount(value: number | Ref<number>) {
    // 确保以下输出为true
    console.log(isRef(value)?value.value:value === 10)
}

initialCount(initial)

/**
 * 挑战 4:
 * 为源响应式对象上的某个 `property` 新创建一个 `ref`。
 * 然后,`ref` 可以被传递,它会保持对其源`property`的响应式连接。
 * 确保以下输出为true
*/
const state = reactive({
    foo: 1,
    bar: 2,
})
const fooRef = toRef(state,'foo') // 修改这里的实现...

// 修改引用将更新原引用
fooRef.value++
console.log(state.foo === 2)

// 修改原引用也会更新`ref`
state.foo++
console.log(fooRef.value === 3)

</script>

<template>
    <div>
        <h1>msg</h1>
        <p>
            <span @click="update(count - 1)">-</span>
            {{ count }}
            <span @click="update(count + 1)">+</span>
        </p>
    </div>
</template>

事件修饰符(stop、once、provent、self)

<script setup lang="ts">

const click1 = () => {
    console.log('click1')
}

const click2 = () => {
    //
    // e.stopPropagation()
    console.log('click2')
}

</script>

<template>
    <div @click="click1">
        <div @click.stop="click2">
            click me
        </div>
    </div>
</template>

响应式丢失

<script setup lang="ts">
import { reactive,toRefs } from 'vue';

function useCount(){
    const state=reactive({
        count:5
    })
    const change=(value:number)=>{
        state.count=value
        console.log(state.count)
    }
    return {
        state:toRefs(state),
        change
    }
}
const {state:{count},change}=useCount()
console.log(count)
</script>

<template>
    <button @click="change(count+1)">+1</button>
    {{ count }}
    <button @click="change(count-1)">-1</button>
</template>

toRefs是为了解决用ref或者reactive创建的响应式对象,被再次赋值或解构为一个新的变量时响应式丢失问题

组件间的 v-model

//父
<Child  v-model:capitalize="first" v-model="last"/>
//子
<script setup lang="ts">
import { computed } from 'vue';

const props=defineProps(['capitalize','modelValue'])
const emits=defineEmits(['update:capitalize','update:modelValue'])
const change=(e:Event)=>{
    let value=(e.target as HTMLInputElement).value
    value=value.charAt(0).toUpperCase() + value.slice(1)
    emits('update:capitalize',value)
}
const value=computed({
    get(){
        return props.modelValue
    },
    set(value){
        emits('update:modelValue',value)
    }
})
</script>

<template>
    <input :value="capitalize" @input="change"/>
    <input v-model="value"/>
</template>

钩子函数 vModelText的使用


<script setup lang="ts">
import { ref, vModelText } from 'vue';
const _vModelText = vModelText

vModelText.beforeUpdate = function (el, binding) {
    if (el.value && binding.modifiers.capitalize) {
        el.value = el.value.charAt(0).toUpperCase() + el.value.slice(1)
    }
}
const v = ref('')
</script>

<template>
  <input type="text" v-model.capitalize="v" />
</template>

props验证

<script setup lang="ts">
interface Props {
    type: "primary" | "ghost" | "dashed" | "link" | "text" | "default"
}

withDefaults(defineProps<Props>(), {
    type: "default"
})
</script>

<template>
    <button>Button</button>
</template>

withDefaults 是 Vue 3 提供的一个工具函数,用于合并两个对象生成一个新的响应式对象

计算属性的读写

<script setup lang="ts">
import { ref, computed } from "vue"

const count = ref(1)
const plusOne = computed({
    get(){
        return count.value + 1
    },
    set(value){
        count.value=value-1
    }
})

/**
 * 确保 `plusOne` 可以被写入。
 * 最终我们得到的结果应该是 `plusOne` 等于 3 和 `count` 等于 2。
*/

plusOne.value++

</script>

<template>
    <div>
        <p>{{ count }}</p>
        <p>{{ plusOne }}</p>
    </div>
</template>

watch的使用

<script setup lang="ts">
import { ref, watch } from "vue"

const count = ref(0)

/**
 * 挑战 1: Watch 一次
 * 确保副作用函数只执行一次 
*/
const unWatch=watch(count, () => {
    console.log("Only triggered once")
    unWatch()
})

count.value = 1
setTimeout(() => count.value = 2)

/**
 * 挑战 2: Watch 对象
 * 确保副作用函数被正确触发
*/
const state = ref({
    count: 0,
})
watch(()=>state.value.count, () => {
    console.log("The state.count updated")
})
// watch(state, () => {
//     console.log("The state.count updated")
// },{
//     deep:true
// })
state.value.count = 2

/**
 * 挑战 3: 副作用函数刷新时机
 * 确保正确访问到更新后的`eleRef`值
*/

const eleRef = ref()
const age = ref(2)
watch(age, () => {
    console.log(eleRef.value)
},{
    flush:"post"
})
age.value = 18

</script>

<template>
    <div>
        <p>
            {{ count }}
        </p>
        <p ref="eleRef">
            {{ age }}
        </p>
    </div>
</template>

shallowRef 的使用

<script setup lang="ts">
import { shallowRef, watch } from "vue"

const state = shallowRef({ count: 1 })

// 回调没被触发
watch(state, () => {
    console.log("State.count Updated")
}, { deep: true })

/**
 * 修改以下代码使watch回调被触发
 *
*/
//下边代码不会触发
state.value.count=2
//正确的做法
state.value = {count:2}

</script>

<template>
    <div>
        <p>
            {{ state.count }}
        </p>
    </div>
</template>

依赖注入

//父
provide('type','张三')
//子孙
const type=inject('type')