生命周期钩子
在setup中使用生命周期函数,直接导入vue中的onX函数注册生命周期:
<script>
import {onMounted, onUpdated,onUnmounted,ref} from 'vue';
export default {
setup(props) {
const counter =ref(0);
const increment=()=>{
counter.value++;
};
onMounted(() => {
console.log("app mounted");
});
onUpdated(() => {
console.log("app updated");
});
onUnmounted(() => {
console.log("app unmounted");
});
return {
counter,
increment
}
}
}
</script>一个生命周期函数可以使用多次。
setup中的provide和inject
在祖父组件中导入并使用provide函数;在子孙节点中导入并使用inject函数:
// App.vue
import {provide, ref, readonly} from 'vue';
import Home from './Home.vue';
export default {
components:{
Home
},
setup(props) {
const name=ref("shopkeeper");
const counter=ref(100);
const increment=()=>{
counter.value++;
};
provide("name",readonly(name));
provide("counter",readonly(counter));
return {
increment,
counter
}
}
}
</script>// Home.vue
<script>
import {inject} from 'vue'
export default {
setup(props) {
// inject函数的第二个参数是指定一个默认值,可以缺省
const name=inject("name");
const counter=inject("counter");
const homeIncrement=()=>{
counter.value++;
}
return {
name,
counter,
homeIncrement
}
}
}
</script>一般的设计习惯是,数据不允许在子孙组件中修改,所以祖父组件在provide函数传参时一般传入readOnly对象。
案例
开发中经常将一个逻辑的模块单独抽取到一个js文件中:
useCounter
import { ref, computed } from 'vue';
export default function(){
const counter=ref(0);
const doubleCounter=computed(()=>counter.value*2);
const increment=()=>counter.value++;
const decrement=()=>counter.value--;
return {
counter,doubleCounter,increment,decrement
}
}useTitle
// useTitle
import { ref,watch } from "vue";
export default function(title = "默认title"){
const titleRef =ref(title);
watch(titleRef,(newValue)=>{
document.title=newValue;
},{
immediate:true
});
return titleRef;
}useScrollPosition
import { ref } from 'vue';
export default function(){
const scrollX=ref(0);
const scrollY=ref(0);
document.addEventListener("scroll",()=>{
scrollX.value=window.scrollX;
scrollY.value=window.scrollY;
});
return {
scrollX,
scrollY
}
}useMousePosition
import { ref } from 'vue';
export default function(){
const mouseX=ref(0);
const mouseY=ref(0);
window.addEventListener("mousemove",(event)=>{
mouseX.value=event.pageX;
mouseY.value=event.pageY;
});
return {
mouseX,
mouseY
}
}useLocalStorage
import { ref, watch } from "vue";
export default function(key ,value){
const data = ref(value);
if (value){
window.localStorage.setItem(key,JSON.stringify(value));
}else{
data.value=JSON.parse(window.localStorage.getItem(key));
}
watch(data,(newValue)=>{
window.localStorage.setItem(key,JSON.stringify(newValue));
});
return data;
}
// 一个参数:取值
// const data = useLocalStorage("name");
// 两个参数:保存值
// const data = useLocalStorage("name","sk");
// data.value="shopkeeper";写一个index.js一次性导入上述的模块:
import useCounter from './useCounter';
import useTitle from './useTitle';
import useScrollPosition from './useScrollPosition';
import useLocalStorage from './useLocalStorage';
import useMousePosition from './useMousePosition';
export {
useCounter,
useTitle,
useScrollPosition,
useLocalStorage,
useMousePosition
}app.vue:
<template>
<div>
<h2>计数器值:{{counter}}</h2>
<h2>计数器值*2:{{doubleCounter}}</h2>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<h2>{{data}}</h2>
<button @click="changeData">change data</button>
<p class="content"></p>
<div class="scroll">
<div class="scroll-x">scroll-x: {{scrollX}}</div>
<div class="scroll-y">scroll-y: {{scrollY}}</div>
</div>
<div class="mouse">
<div class="mouse-x">mouse-x: {{mouseX}}</div>
<div class="mouse-y">mouse-y: {{mouseY}}</div>
</div>
</div>
</template>
<script>
// import { ref, computed } from 'vue';
import {
useCounter,
useTitle,
useScrollPosition,
useLocalStorage,
useMousePosition
} from './hook';
export default {
setup(props) {
// counter
const { counter, doubleCounter, increment, decrement} = useCounter();
// title
const titleRef=useTitle("sk");
setTimeout(()=>{
titleRef.value="shopkeeper";
},3000);
// 滚动位置
const { scrollX,scrollY } = useScrollPosition();
// 鼠标位置
const { mouseX, mouseY} =useMousePosition();
// 数据保存
const data=useLocalStorage("info",{name:"sk",age:18});
const changeData=()=>{
data.value="hahaha";
};
return {
counter, doubleCounter, increment, decrement,
scrollX, scrollY,
mouseX, mouseY,
data, changeData
}
}
}
</script>
<style scoped>
.content{
width: 3000px;
height: 5000px;
}
.scroll{
position: fixed;
right: 30px;
bottom: 30px;
}
.mouse{
position: fixed;
right: 30px;
bottom: 80px;
}
</style>