学习vue第二天

学习vue第二天
麟玖SamtoRef方法
- toRef方法用于将响应式数据内部的普通数据转换为响应式数据,并且转化后的数据和原始的数据纯在引用关系,存在引用关系意味着原始数据发生变化后,toRef转换后的数据也会根着变化
export default{
setup(){
const person = ref({name:"张三"})
return { name: toRef(person.value.name)}
}
}
toRefs方法
- 通过
toRef
方法一次只能转换一个数据,通过toRefs
方法可以实现批量数据转换。 - toRefs 方法接收引用数据类型的响应式数据,它可以将数据中的第一层属性全部转换为响应式数据, 返回值是一个对象, 对象中存储了所有转换之后的响应式数据。
export default {
name: "App",
setup() {
const person = reactive({
name: "张三",
age: 20,
brand: { title: "宝马", year: 1 },
});
return { ...toRefs(person) };
},
};
组件通讯
- 父组件通过 props 向子组件传递数据
<template>
<div>I am parent component</div>
<hr />
<ChildComp :msg="msg"></ChildComp>
</template>
<script>
import ChildComp from "./components/ChildComp.vue"
import { ref } from "vue"
export default {
components: { ChildComp },
setup() {
const msg = ref("a message from parent")
return { msg }
},
}
</script>
<template>
<div>
{{ childMsg }}
<hr />
{{ msg }}
</div>
</template>
<script>
import { computed } from "vue";
export default {
name: "ChildComponent",
props: ["msg"],
setup(props) {
// 当父组件更新 props 时 setup 函数是不会重新执行的
// 所以在 setup 函数中使用 props 时需要用到 computed 或者 watch 来响应 props 的变化
// 注意: 直接在模板中使用 props 数据是没有这个问题的
const childMsg = computed(() => props.msg + "😀😀");
return { childMsg };
},
};
</script>
- 子组件通过自定义事件向父组件传递数据
<template>
<div>
{{ childMsg }}
<hr />
{{ msg }}
<hr />
<button @click="onMsgChanged">change msg</button>
</div>
</template>
<script>
import { computed } from "vue";
export default {
name: "ChildComponent",
props: ["msg"],
setup(props, { emit }) {
const onMsgChanged = () => {
emit("onMsgChanged", "changed msg from children");
};
return { onMsgChanged };
},
};
</script>
<template>
<ChildComponent :msg="msg" @onMsgChanged="onMsgChanged" />
</template>
<script>
import { ref } from "vue";
import ChildComponent from "./components/child-component.vue";
export default {
components: { ChildComponent },
name: "App",
setup() {
const msg = ref("i am a message");
const onMsgChanged = (data) => {
msg.value = data;
};
return { msg, onMsgChanged };
},
};
</script>
组件生命周期
- setup 组件初次挂在前,重新挂载前都会执行
- onMounted 组件挂载完成后执行
- onUpdated 组件数据更新后执行
- onUnmounted 组件卸载后执行
与服务端通信
- 向服务器端发送请求获取列表数据渲染列表数据, 没有数据要显示暂无数据, 如果请求报错展示错误信息, 加载过程显示loading.
<script>
import { ref } from "vue";
import axios from "axios";
export default {
name: "App",
setup() {
// 用于存储列表数据
const data = ref(null);
// 用于标识加载状态
const loading = ref(false);
// 用于存储错误信息
const error = ref(null);
// 用于发送请求的方法
async function getPosts() {
// 更新加载状态
loading.value = true;
try {
// 发送请求
let response = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
// 存储列表数据
data.value = response.data;
} catch (err) {
// 存储错误信息
error.value = err.message;
}
// 更新加载状态
loading.value = false;
}
// 调用方法 发送请求
getPosts();
// 返回模板所需数据
return { data, loading, error };
},
};
</script>
获取DOM对象
- 获取单个DOM对象
import { ref, onMounted } from "vue"
export default {
setup() {
const divRef = ref(null)
onMounted(() => {
console.log(divRef.value)
})
return { divRef }
},
}
- 获取一组 DOM 对象
import { ref, onMounted, onUpdated } from "vue"
export default {
setup() {
const list = ref(["a", "b", "c"])
const elms = ref([])
const onClickHandler = () => list.value.push("d")
onMounted(() => console.log(elms.value))
onUpdated(() => console.log(elms.value))
return { list, elms, onClickHandler }
},
}
provide, inject函数
- 通过 provide、inject 函数的配合使用,可以实现跨组件传递数据(组件与组件存在嵌套关系)
<!-- 父组件 App -->
<template>
<ChildComponent />
</template>
<script>
import { ref, provide } from "vue";
import ChildComponent from "./components/ChildComponent.vue";
export default {
components: { ChildComponent },
name: "App",
setup() {
const person = ref({ name: "张三" });
const changePerson = () => {
person.value.name = "李四";
};
provide("person", person);
provide("changePerson", changePerson);
},
};
</script>
<!-- 子组件 -->
<template>
<LastComponent />
</template>
<script>
import LastComponent from "./LastComponent.vue";
export default {
components: { LastComponent },
name: "ChildComponent",
};
</script>
<!-- 孙组件 -->
<template>
{{ person.name }}
<button @click="changePerson">button</button>
</template>
<script>
import { inject } from "vue";
export default {
name: "LastComponent",
setup() {
const person = inject("person");
const changePerson = inject("changePerson");
return { person, changePerson };
},
};
</script>
teleport组件
- teleport 组件可以将指定组件渲染到应用外部的其他位置。
- 比如弹框组件,它可能在任意组件中使用,但它不属于任意组件,所以不能在使用它的组件中渲染它,我们需要将它渲染到指定位置。
<!-- Modal.vue -->
<template>
<div class="wrapper">
<div class="content">
<a class="close" href="javascript:">关闭</a>
</div>
</div>
</template>
<script>
export default {
name: "Modal",
};
</script>
<style scoped>
.wrapper {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.content {
width: 660px;
height: 400px;
background: white;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.close {
position: absolute;
right: 10px;
top: 10px;
color: #999;
text-decoration: none;
}
</style>
<!-- App.vue -->
<template>
<teleport to="#modal">
<Modal />
</teleport>
</template>
<script>
import Modal from "./components/Modal.vue";
export default {
components: { Modal },
name: "App",
};
</script>
Suspense组件
- Suspense 用于确保组件中的 setup 函数调用和模板渲染之间的执行顺序。先执行 setup 后渲染模板。
- 当组件中的 setup 被写成异步函数的形式, 代码执行的顺序就变成了先渲染模板后执行 setup 函数了。
<!-- Posts.vue -->
<template>
<pre>{{ data }}</pre>
</template>
<script>
import axios from "axios";
export default {
name: "Posts",
async setup() {
let response = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
return { data: response.data };
},
};
</script>
<!-- App.vue -->
<template>
<Suspense>
<Posts />
</Suspense>
</template>
<script>
import Posts from "./components/Posts.vue";
export default {
components: { Posts },
name: "App",
};
</script>
过度动画
- Vue 提供了 transition 组件供我们执行过渡动画, 我们只需要使用 transition 组件包裹你要执行动画的元素即可。
- 执行过渡动画的前提条件是元素具有创建与销毁的操作
- 当创建元素时, transiton 组件会为执行动画的元素添加三个类名, 我们可以通过这三个类名为元素添加入场动画。
.v-enter-from {} // 元素执行动画的初始样式 (动画起点样式)
.v-enter-to {} // 元素执行动画的目标样式 (动画终点样式)
.v-enter-active {} // 可以用于指定元素指定动画的类型
.v-enter-from { opacity: 0 }
.v-enter-to { opacity: 1 }
.v-enter-active { transition: opacity 2s ease-in } // ease-in 先慢后快
- 当销毁元素时, transition 组件会为执行动画的元素添加三个类名, 我们可以通过这个三个类名为元素添加离场动画样式。
.v-leave-from {} // 元素执行动画的初始样式 (动画起点样式)
.v-leave-to {} // 元素执行动画的目标样式 (动画终点样式)
.v-leave-active {} // 可以用于指定元素指定动画的类型
.v-leave-from { opacity: 1 }
.v-leave-to { opacity: 0 }
.v-leave-active { transition: opacity 2s ease-out } // ease-out 先快后慢
- 如果在页面中有多个元素要执行动画, 而多个元素要执行的动画不同时, 为了对多个元素的动画样式进行区分, 在调用 transiton 组件时需要为它添加 name 属性以区分样式类名。
<transition name="fade">
<h1>hello world</h1>
</transition>
.fade-enter-from {}
.fade-enter-to {}
.fade-enter-active{}
.fade-leave-from {}
.fade-leave-to {}
.fade-leave-active {}
状态管理Vuex
- 首先vue3只能使用vuex4版本。
#首先安装vuex
npm i vuex
#然后在src目录下创建一个store文件来存放代码
import { createStore } from 'vuex'
export default createStore({
state: {
name:"小王"
},
mutations: {
},
actions: {
},
modules: {
}
})
#在mian.js中导入
import { createApp } from 'vue'
import App from './App.vue'
import store from './store';
const app = createApp(App)
app.use(store);
app.mount('#app')
#页面展示
<template>
<div>
<div>{{ store.state.name }}</div>
</div>
</template>
<script setup lang="ts">
import { useStore } from "vuex";
const store = useStore();
</script>
<style scoped>
</style>
双向数据绑定
- 双向数据绑定是指数据和视图进行绑定,数据变化同步视图,视图更改了数据,将更改同步回数据
- App.vue
<template>
<Test v-model:firstName="firstName" v-model:lastName="lastName" />
<button @click="onClickHandler">我是App组件中的 button</button>
</template>
<script>
import Test from "./components/Test.vue";
import { ref } from "vue";
export default {
components: { Test },
name: "App",
setup() {
const firstName = ref("张三");
const lastName = ref("李四");
const onClickHandler = () => {
firstName.value = "孙悟空";
lastName.value = "猪八戒";
};
return { firstName, lastName, onClickHandler };
},
};
</script>
- Test.vue
<template>
<div>
{{ firstName }} {{ lastName }}
<button @click="onClickHandler">我是Test组件中的button</button>
</div>
</template>
<script>
export default {
props: ["firstName", "lastName"],
setup(props, { emit }) {
const onClickHandler = () => {
emit("update:firstName", "刘备");
emit("update:lastName", "诸葛亮");
};
return { onClickHandler };
},
};
</script>
customRef
- 防抖:监听用户的连续操作,最终指响应连续操作中的最后一次操作
< script setup>
const keyword = useDeb("Holle", 400);
function useDeb(initalValue, delay) {
let timer = null;
return customRef((track, trigger) => {
return {
get() {
track();
return initalValue;
},
set(newValue) {
clearTimeout(timer);
timer = setTimeout(() => {
initalValue = newValue;
trigger();
}, delay);
},
};
});
}
</script>
<template>
<input type="text" v-model="keyword" />
{{ keyword }}
</template>
Vue3语法糖
<script setup></script>
是一种编译时语法糖,用于在单文件组件中使用组合式API,如果你同时使用单文件组件和组合式API,建议使用该语法。
- 子组件可不用手动注册
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果