当前位置: 代码迷 >> 综合 >> Vue3.0上手
  详细解决方案

Vue3.0上手

热度:77   发布时间:2023-11-21 02:46:19.0

生命周期钩子

vue3.0提供了 setup onMounted onUnmounted onUpdated 生命周期钩子,都在vue 上。

import { onMounted, onUpdated, onUnmounted } from 'vue'const MyComponent = {setup() {onMounted(() => {console.log('mounted!')})onUpdated(() => {console.log('updated!')})onUnmounted(() => {console.log('unmounted!')})}
}

vue2.0和vue3.0之间生命周期区别

  • beforeCreate -> use setup()* created -> use setup()* beforeMount -> onBeforeMount* mounted -> onMounted* beforeUpdate -> onBeforeUpdate* updated -> onUpdated* beforeUnmount -> onBeforeUnmount* unmounted -> onUnmounted* errorCaptured -> onErrorCaptured* renderTracked -> onRenderTracked* renderTriggered -> onRenderTriggered

setUp 函数

执行时间

在创建组件实例时,在初始 prop 解析之后立即调用 setup。在生命周期方面,它是在 beforeCreate 钩子之前调用的。

函数

setup 函数接受两个参数,第一个参数 props第二个参数 context

props

props是响应式的,在传入新的 props 时会对其进行更新,并且可以通过使用 watchEffectwatch 进行观测和响应,不要对props进行解构赋值,解构之后将不具有响应性。

export default {props: {name: String},setup(props) {watchEffect(() => {console.log(`name is: ` + props.name)})}
}

context:执行上下文

常用的 emit slots attrs 在context可以获取到。

export default defineComponent({name: "CardList",components: { Blank },props: {list: {type: Array,default: () => {return [];},},},setup(props, context) {// 实例化 routerconst router = useRouter();const toView = (item) => {router.push({ name: "Article", query: { id: item.id } });};const like = (index) => {context.emit("like", index);};return {toView,like,};},
});

computedwatch的使用,filters移出

filters 不在vue3中支持,官方推荐使用computed来代替filter的使用

computedwatch 也是在vue上的,使用之前需要import导入。

import { computed, watch, ref } from 'vue';
....
setup() {const route = useRoute();const name = ref('pe');const computedA = computed(() => {return name.value + '--nameA'})const computedB= computed(() => {return name.value + '--nameB'})watch(route,(nowVal,preVal) => {// do some thing})watch(name,(nowVal,preVal) => {// do some thing})watch([() => count, () => name]([count, name], [preCount, preName]) => { //count新值, preCount旧值console.log('log输出') //这里是监听数据变化后执行的函数}, {lazy: false})//在第一次创建不监听return {computedA,computedB}
} 

ref reactive toRef toRaw 是什么?怎么用?

ref

ref接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value

ref将一个变量进行代理实现了响应式,想要访问这个变量的值必须获取变量的value 才能访问得到。

<div><span>{
   {name}}</span><span>{
   {age}}</span><button @click="change">AGE+1</button>// 点击按钮 发现 age + 1,但是 name没有变化
</div>
...
setup() {let name = 'hs'const age = ref(10);const change = () => {name  = 'hs' + '1'age.value = age.value += 1;console.log(name,age.value);}
} 

点击button 发现 age+ 1,但是 name没有变化,还是原来的值。

日志输入:age: 11;name: hs1

name数据改变了但是页面没有更新,因为name不是响应式数据

通过ref获取Dom?

在vue2中我们想要获取Dom的时候,可以在dom上添加ref,然后通过$refs获取到Dom, 在vue3中,我们通过提供的ref方法传入一个null并且定义与页面元素上ref相对应。

<template><div><h1 ref="h1Ref">Hello Word</h1></div>
</template>
<script>
import { ref, onMounted } from '@vue/composition-api'
export default {setup() {// 创建一个 DOM 引用const h1Ref = ref(null)// 在 DOM 首次加载完毕之后,才能获取到元素的引用onMounted(() => {// 为 dom 元素设置字体颜色// h1Ref.value 是原生DOM对象console.log(h1Ref.value)})// 把创建的引用 return 出去return {h1Ref}}
}
</script>

reactive

reactive定义引用类型的响应式数据,定义的数据不需要和ref一样通过value获取值,可以直接获取

setup() {// const bh = reactive(10) => errorconst bh = reactive({val: 10};const getBh = () => {return bh; // 直接返回}return {bh,}
}

toRef

toRef: 可以用来为源响应式对象上的 property 性创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。

const state = reactive({foo: 1,bar: 2
})const fooRef = toRef(state, 'foo')fooRef.value++
console.log(state.foo) // 2state.foo++
console.log(fooRef.value) // 3

上案例,将statefoofooRef绑定了,可以说fooRef是对state.foo的引用,并在外层包裹了一层ref 。在实际的开发中,如果想要得到某个多层的对象下面的属性时,可以采用toRef

toRaw

toRaw :返回 reactivereadonly 代理的原始对象。

const foo = {}
const reactiveFoo = reactive(foo)console.log(toRaw(reactiveFoo) === foo) // true

hooks引入,可以做什么?

hooks 提高了代码的复用性,代码逻辑清晰。

hooks可以在组件外部调用Vue的所有能力,包括onMounted,ref, reactive等等。

useMousePosition.ts

// hooks
import {onBeforeUnmount, onMounted, ref} from 'vue
export default function () {const x = ref(-1) ; // x 绑定为响应式数据const y = ref(-1);const clickHandler=(event:MouseEvent)=>{x.value = event.pageXy.value = event.pageY} onMounted(()=>{window.addEventListener('click', clickHandlker)})onBeforeUnmount(()=>{window.removeEventListner('click', clickHandler)})return {x,y}
}
<template>
<div><h2>x: {
   {x}}, y: {
   {y}}</h2>
</div>
</template><script>import {ref
} from "vue"
/* 
在组件中引入并使用自定义hook
自定义hook的作用类似于vue2中的mixin技术
自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂
*/
import useMousePosition from './hooks/useMousePosition'export default {setup() {const {x, y} = useMousePosition() // 这里就用了 hooks 函数, 从而提高了复用性return {x,y,}}
}
</script>

Teleport组件

teleportvue3新增的组件。他可以让我们将组件插入到指定的Dom结构下。

使用案例:

在项目中,有一个场景:在页面滚动区域过长的情况下,需要能够一键回到顶部的这样一样操作按钮。

在Vue3中,就可以利用Teleport来实现这个功能。只需要操作按钮组件编写完成,然后将Teleportto属性绑定到置顶的Dom上即可。

toUper.vue

<template><!-- #app 代表这个 Dom将要挂载到id为App的dom下方 --><teleport to="#app"><div class="toUpper animated flash" v-if="show"><div class="ic" @click="toHome()"><i class="iconfont icon-shouye1"></i></div><div class="ic" @click="toUp()"><i class="iconfont icon-up"></i></div></div></teleport>
</template>
<script>
import { defineComponent } from "vue";
import { useRouter } from 'vue-router';
import useScrollToTop from "@/hooks/useScrollToTop";
export default defineComponent({name: "ToUpper",props: {show: {type: Boolean,default: false,},},setup() {const router = useRouter();const toUp = () => {useScrollToTop();};const toHome = () => {router.push({path: '/'});}return {toUp,toHome,};},
});
</script><style lang="scss" scoped>
.toUpper {position: sticky;top: 90%;left: 90%;
}
.ic {float: right;display: block;margin-right: 40px;width: 40px;height: 40px;border-radius: 50%;background: #528bff;display: flex;align-items: center;justify-content: center;&:hover {cursor: pointer;}.iconfont {color: #fff;}
}
</style>

Home.vue

<template><div class="home" if="home"><Header @changStatus="changStatus" :status="status" /><div class="main"><router-view></router-view><div id="upper"></div></div><!-- 当页面滚动区域操作20之后才显示  --><to-upper :show="scrollTop > 20" /></div>**
**</template>

provide & inject(数据共享)

provide()和 inject()可以实现嵌套组件之间的数据传递。这个两个函数只能在setup()函数中使用。父级组件中使用provide()函数可以使数据向下传递,子组件中使用inject()接收上层传过来的数据。
实现代码:
根组件(父组件)parent.vue

<template><div><child-one></child-one><child-two></child-two></div>
</template><script>import { provide } from '@vue/composition-api'import ChildOne from '@/components/Child'import ChildTwo from '@/components/Child'export default {components: {ChildOne,ChildTwo},setup() {// provide('要共享的数据名称', 被共享的数据)provide('globalName', 'vue') }}
</script>

childOne.vue

<template><div><!--页面展示数据globalName -->{
   {globalName}} </div>
</template><script>import { inject } from '@vue/composition-api'export default {name: 'ChildOne',setup() {const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据return {globalName}}}
</script>

childTwo.vue

<template><div><!--页面展示数据globalName -->{
   {globalName}} </div>
</template><script>import { inject } from '@vue/composition-api'export default {name: 'ChildTwo',setup() {const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据return {globalName}}}
</script>

APP配置

config是一个包含了 Vue 应用全局配置的对象。你可以在应用挂载前修改其下属性:

errorHandler: 错误的处理回调

warnHandler: 警告的处理回调

globalProperties:全局的属性

optionMergeStrategies:自定义项合并策略

performance: 性能调试。接受布尔值,设置为 true 。可以在 浏览器开发工具的 performance/timeline 面板中启用对组件初始化、编译、渲染和更新的性能追踪

import App from './App.vue'
const app = crateApp(App);
app.config.errorHandler = (err) => {}; //处理错误回调
app.config.warnHandler= (warn) => {}; //
app.config.globalProperties.isAndroid = true;
app.config.performace = true; // 开启性能调试 

vue3项目参考

Gitee