生命周期钩子
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
-> usesetup()
*created
-> usesetup()
*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 时会对其进行更新,并且可以通过使用 watchEffect
或 watch
进行观测和响应,不要对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,};},
});
computed
、 watch
的使用,filters
移出
filters
不在vue3中支持,官方推荐使用computed
来代替filter
的使用
computed
、watch
也是在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
上案例,将state
的foo
和fooRef
绑定了,可以说fooRef
是对state.foo
的引用,并在外层包裹了一层ref
。在实际的开发中,如果想要得到某个多层的对象下面的属性时,可以采用toRef
,
toRaw
toRaw
:返回 reactive
或 readonly
代理的原始对象。
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组件
teleport
是vue3
新增的组件。他可以让我们将组件插入到指定的Dom
结构下。
使用案例:
在项目中,有一个场景:在页面滚动区域过长的情况下,需要能够一键回到顶部的这样一样操作按钮。
在Vue3中,就可以利用Teleport
来实现这个功能。只需要操作按钮组件编写完成,然后将Teleport
的to
属性绑定到置顶的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