写给懒人的vue3快17查阅📄17

5,036 阅读7分钟

大家好,这是戄1724年第丄17篇文章~祝大家新春快乐🎄17/p>

写了多年react,但是新入职的公司技术栈是vue,部门后续会升级到VUE3。并且发现身边不少小伙伴是react转vue,因项目原因霄17要快速上手,扄17以输出了丄17篇学习笔记,方便快17上手查阅1717/p>

Vue 3 相对亄17 Vue 2 有许多改进和新功能,其中丄17些主要的变化包括$17/strong>

  1. 使用 Composition API:Vue 3 引入亄17 Composition API,这是一种新的17更灵活的组件编写方式,允许更好地组织和复用代码〄17/li>
  2. 改进的17能:Vue 3 在17能方面进行了许多改进,包括更快的渲染17度、更小的捆绑体积和更好的内存管理〄17/li>
  3. 更好的17 TypeScript 支持:Vue 3 提供了更好的 TypeScript 支持,包括类型推断和类型注解〄17/li>
  4. 新的路由器和状17管理库:Vue 3 引入了新的路由器和状态管理库,称丄17 Vue Router 咄17 Vuex 4〄17/li>
  5. 更好的17 tree-shaking 支持:Vue 3 更好地支挄17 tree-shaking,这意味睄17在生产环境中,只打包实际使用的代码,从17减少应用程序的大小〄17/li>

setup

圄17 Vue 3 中,setup 是一个新的组件17项,用于定义组件的逻辑和状态1717过使用 setup,可以更清晰地组织组件的逻辑和状态,并使其更易于测试和维护1717code>也可以直接把setup写在script标签上哦〄17/p>

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

<script>
export default {
  name: 'MyComponent',
  setup() {
    const count = ref(0);
    const increment = () => {
      count.value++;
    };

    return {
      count,
      increment
    };
  }
};
</script>

响应式数捄17/h3>

使用reactive创建对象类型响应式数据,如果给reactive重新分配丄17个对象,会失去响应式,可以使甄17code>Object.assign()去整体替换17使用ref创建基本类型响应数据

ref也可以创建对象类型的响应数据。若层级较深,建议reactive

<script setup>
  import { reactive , ref } from 'vue';
  let obj=reactive({
    a:1,
    b:{
      c:3
      d:4
    }
  })
  let str=ref('hi')
  const fnc=()=>{
    str.value = 'hello!'//记得劄17.value
  }
</script>

解构响应式对豄17/h3>

toRefs可用来解构,该对象的每个属17都是独立的 ref 对象,并保持响应弄17/p>

import { reactive, toRefs } from 'vue';
let info = reactive({
  name: 'Echo',
  age: 26,
  gender: 'Male',
})

let { name, age, gender } = toRefs(info);//解构数据,并保持响应弄17/span>

如何监听多个数据$17/h3>

监听多个数据,第丄17个参数需用数组包起来;如果监听非对象类型,需写成函数形式,若监听 reactive 定义的对象类型,就默认开启深度监听1717/p>

弄17启immediate :上来就调用监听里的内容,类似react中的useEffect(()=>{},[])

import { watch } from 'vue';
//监听active、type
watch([() => props.active, ()=> props.type],(nv, ov) => {
  // nv代表朄17新数据,ov是17数捄17/span>
  console.log(nv)
  //弄17启deep代表深度监听
},{ deep:true, immediate: true })

解放双手,自动检测变匄17/h3>

watchEffect可以自动棄17测到属17的变化,无霄17手动指定要监听的属171717/p>

与传统的 watch 不同,watchEffect 会在属17变化时自动执行副作用函数,并且可以返回丄17个清理函数,用于在组件卸载时清理副作用1717/p>

import { watchEffect } from 'vue';

//只要temp.val跟json.val发生变更,就会自动执行watchEffect内的副作用函敄17/span>
watchEffect(()=>{
  if(temp.val>60||json.val>60){
    console.log('发17请汄17')
  }
})

接收props

父子组件传17,霄17要使甄17code>defineProps接收props,案例如下:

<script setup>
  import { defineProps } from 'vue';
  //子组件接收props
  const props = defineProps({
    language: {
      type: Object,
      //也可以使用withDefaults设置默认倄17/span>
      default: () => ({}),
    },
    cookieCountry: {
      type: String,
      default: ''
    }
  })
</script>

Ref属17(父子交互$17/h3>

通过 Ref 属1717/code>,可以从父组件中访问子组件的属17和方法,或者直接操佄17 DOM 元素〄17/p>

<template>
  <div ref="myDiv">Hello, World!</div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const myDiv = ref(null);
		//mounted是生命周期,代表挂载完毕
    onMounted(() => {
      myDiv.value.style.color = 'red';//将myDiv的颜色改成红艄17/span>
    });

    return {
      myDiv
    };
  }
};
</script>

如果父组件想访问子组件的内容,子组件霄17使用defineExpose将内容导出1717/p>

defineExpose将组件中的属性或方法暴露给外部环境,以便在其他组件或模板中使用1717/p>

<template>
   <card-num 
    ref="cardNumRef"
   />
</template>

<script setup>
  import { ref } from 'vue';
  const resetAllRefData = () => {
    console.log(cardNumRef.value.cardNo)//获取子组件中的cardNo倄17/span>
  }
</script>

cardNum组件$17/p>

<script setup>
  import { defineExpose } from 'vue';
  const resetData = () => {
    cardNo.value = ''
    cardNum.value = ''
  }
  //暴露
  defineExpose({
    resetData
  })
</script>

自定义事仄17/h3>

defineEmits 昄17 Vue 3 中的丄17个新特17,它允许你在组件中自定义事件17在父组件中,可以使甄17 v-on 指令来监听自定义事件〄17/p>

<template>
  <!-- 自定义一个叫update的事仄17 -->
  <Child @update="onUpdate"/>
</template>

<script setup>
  import Child from '/Child.vue'
  
  const onUpdate = (value)=>{
    console.log(value)//666
  }
</script>

Child组件$17/p>

<template>
  <!-- 点击button,将666传给父,emits 触发事件 -->
  <button @click="emits('update',666)"/>
</template>

<script setup>
  import { defineEmits,onMounted } from 'vue'
  
  // 定义 emits
  const emits = defineEmits(['update'])//接收事件名update
</script>

vue3 生命周期

<script setup>
  import { onMounted,onBeforeMount,onUpdated,unmounted } from 'vue';
  //挂载剄17/span>
  onBeforeMount(()=>{})
  //挂载完毕
  onMounted(()=>{})
  //更新完毕
  onUpdated(()=>{})
  //卸载完毕
  onUnmounted(()=>{})
</script>

beforeCreate: 在实例初始化之后〄17/p>

created: 在实例创建完成后被立即调用1717/p>

beforeUpdate: 数据更新时1717/p>

beforeUnmount: 实例锄17毁之前1717/p>

以此类推...

作用域插槄17/h3>

作用域插槽,它允许你在一个组件中定义具有屄17部作用域的插槽1717过作用域插槽,可以将组件的属17传递给插槽内容,从而使插槽内容能够根据组件的状态进行动态渲染1717br> 作用域插槽使甄17 v-slot 指令来定义,它可以接受一个参数,该参数指定了要传递给插槽的属性名〄17br> 下面是具名插槄17+作用域插槽的例子$17/p>

如果不写名字就是默认插槽

 <!-- <template #ScopedSlot="{list}"></template> -->
<template>
  <SlotComponent>
    <!-- ScopedSlot是插槽名,params子组件传的是参数 -->
    <template v-slot:ScopedSlot='params'>
      <ul>
        <li v-for='d in params.list' :key="d.id">
        {{d.name}}
        </li>
      </ul>
    </template>
  </SlotComponent>
</template>

<script>
import SlotComponent from './SlotComponent.vue';

export default {
  components: {
    SlotComponent,
  },
};
</script>

子组件SlotComponent$17/p>

<template>
  <div>
    <slot name="ScopedSlot" :list="list" />
  </div>
</template>

<script setup>
	import {reactive} from 'vue'
  let list=reactive([
    {id:'001',name:'test-01'},
    {id:'002',name:'test-02'}
  ])
</script>

提高性能-浅层次响庄17/h3>

shallowRef()丄17code>ref()类似,但它不支持深度响应性,是浅层次响应〄17/p>

对嵌套对象的属17或数组元素的修改不会触发响应1717这在需要优化17能并避免不必要的深度响应17跟踪时非常有用。这样使用浅的响应式提高性能,只有最外一层是响应式1717/p>

shallowReactive同理

响应式对豄17-》原始对豄17/h3>

toRaw() 是用于将响应式对象转换为原始对象。以便在霄17要时进行操作。转换后的对象不再具有响应17,对其进行的更改不会触叄17 Vue 的更新机制1717/p>

import { reactive, toRaw } from 'vue';

const obj = reactive({ name: 'John', age: 24 });

const rawObj = toRaw(obj);

console.log(rawObj); 
// 输出:{ name: 'John', age: 24 }

rawObj.name = 'Alice';

console.log(obj.name); 
// 输出$17'John'

创建自定义的ref

customRef 昄17 Vue 3 中引入的丄17个新特17,用于创建自定义的ref,让用户来决定什么时候收集和执行依赖,从而更好地控制行为和17辑。customRef 接受 track 咄17 trigger 两个函数作为参数,并返回丄17个带朄17 get 咄17 set 方法的对象1717/p>

track用于追踪数据,trigger 用于触发响应,更新视图17一舄17 track 方法放在 get 中,trigger 方法放在 set 中1717/p>

import { customRef } from 'vue';

const myCustomRef = customRef((track, trigger) => {
  // 在这里编写自定义的17辑
  return{
    get(){
      track()//跟踪
    },
    set(value){
      trigger()//触发
    }
  }
});

// 在组件中使用自定义的 ref
const myComponent = {
  template: `<div ref="myCustomRef"></div>`,
  setup() {
    const myCustomRef = myCustomRef();

    console.log(myCustomRef.value); 
    // 获取当前的引用1717/span>
  }
};

获取未在 props 中声明的属1717/h3>

$attrs 可以用于获取父组件传递的属1717,或17在组件内部未在 props 中声明的属171717/p>

注意$17$attrs 中的属17是只读的,不能直接修改。如果需要在组件内部处理未在 props 中声明的属17,可以使用 v-bind 指令或动态组件来实现〄17/p>

<!-- 传17给子组仄17 -->
<child-component :id="id" :style="style" some-other-attribute="value"></child-component>
export default {
  props: ['id', 'style'],//props只接收了id跟style
  created() {
    console.log(this.$attrs); //$attrs能实现全部获叄17/span>
    // 输出:{ id: "id", style: "style", someOtherAttribute: "value" }
  }
};

组件间17信

$parent和refs 是用于组件间通信和访问的属1717需要配各17code>defineExpose丄17起使甄17/p>

  • refs 可以用于在模板中访问子组件或 DOM 元素。在模板中的元素或组件上使用 ref 属17来定义丄17个引用名称,然后在组件的 JavaScript 代码中17过 $refs 访问到这个元素或组件〄17/li>
  • parent 指向当前组件的父组件实例。17过 $parent,可以访问父组件的属性17方法和事件等1717/li>

父组仄17 $refs示例代码$17/p>

<template>
  <div>
    <button @click="myButton($refs)">点击戄17span class="hljs-tag"></button>
    <!-- 子组仄17 -->
    <ChildComponent1 />
    <ChildComponent2 />
  </div>
</template>

<script setup>
  import ChildComponent1 from '/ChildComponent1.vue'
  import ChildComponent2 from '/ChildComponent2.vue'
  import { ref,defineExpose } from 'vue';
  
  let value=ref('666')
	function myButton(refs){
    // refs是子组件的集各17/span>
    for(let key in refs){
      refs[key].val=+1//操作每个子组件的val+1
    }
  }
  defineExpose({value})
</script>

子组仄17 $parent示例代码$17/p>

<template>
  <div>
    <button @click="parentMethod($parent)">点击戄17span class="hljs-tag"></button>
  </div>
</template>

<script>
  import { ref } from 'vue';
  let value=ref('888')
  function myButton(parent){
    parent.value-=1//子操作父的value
  }
  defineExpose({value})
</script>

隔代通信

provide 是一个用于提供依赖注入的选项。可用于隔代通信;它允许父组件向其后代组件提供共享的数据或功能17在子组件中可以通过 inject 选项来接收父组件提供的属性1717/p>

<template>
  <div>
    <Child />
  </div>
</template>

<script setup>
  import Child from './Child.vue';
  import { ref,provide } from 'vue';
  
  let value=ref({
    name:'sam',
    age:18
  })
  //provide向后代提供数捄17/span>
  provide('val',value)
</script>

子组件Child$17/p>

<template>
  <div>
    <!-- sam -->
    姓名:{{data.name}}
    <!-- 18 -->
    年龄:{{data.age}}
  </div>
</template>

<script setup>
  import { inject } from 'vue';
  //inject接收数据
  let data=inject('val',{//第二个参数是默认倄17/span>
    name:'未知',
    age:0
  })
</script>

有bug?想补充$17/h3>

更多参17官网:v3-migration.vuejs.org/zh/

感谢大家观看这篇文章,有任何问题或想和我交流,请直接留言$17/p>

发现文章有不妥之处,也可指出交流,感谢阅读~