Article directory
scene reason
We need to use the server's data to render to the page in vue3. I use the responsive data attribute generated by reactive, but the requested data is not rendered and displayed on the page after mounting.
Technology:
vue3
,element-ui-plus
1. Examples
home.vue
<template>
<div class="common-layout">
<el-menu @select="changeMenu" :collapse="isCollapse" active-text-color="#409eff" background-color="#333744"
class="el-menu-vertical-demo" default-active="2" text-color="#fff" :unique-opened="true">
<el-sub-menu :index="item.path" v-for="(item) in parmar.menus" :key="item.id">
<template #title>
<el-icon>
<List />
</el-icon>
<span>{
{ item.authName }}</span>
</template>
<el-menu-item :index="item2.path" v-for="(item2) in item.children" :key="item2.id">
<el-icon>
<Menu />
</el-icon>
{
{ item2.authName }}
</el-menu-item>
</el-sub-menu>
</el-menu>
</div>
</template>
<script setup>
// 引入模块
import {
reactive, onMounted } from 'vue'
import {
useRouter } from 'vue-router'
import http from '@/utils/request'
const router = useRouter();
let menusList = reactive([
]);
onMounted(() => {
getData()
})
const getData = async () => {
let {
data } = await http.get('/menus');
// 这里直接赋值,会导致menusList失去响应式了
menusList = data.data;
console.log(menusList);
}
const changeMenu = (key) => {
router.push('/home/' + key)
}
</script>
<style lang="less" scoped>
.common-layout {
height: 100vh;
box-sizing: border-box;
position: relative;
overflow: hidden;
/deep/.el-menu--vertical {
margin: 0;
border-right: none !important;
overflow-x: hidden;
height: calc(100vh - 100px);
user-select: none;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
}
</style>
Through direct assignment, we can see that the data has become ordinary data, not responsive.
Two, the solution
1. Use ref to store responsive data
code show as below:
<script setup>
// 引入模块
import {
ref, reactive, onMounted } from 'vue'
import http from '@/utils/request'
let menusList = ref([
]);
onMounted(() => {
getData()
})
const getData = async () => {
let {
data } = await http.get('/menus');
// 这里直接赋值value,在页面上直接使用menusList即可!
menusList.value = data.data;
}
</script>
It can be seen that the printed data is data hijacked by ref and is responsive.
2. Use objects to wrap the data to be changed in reactive
code show as below:
<script setup>
// 引入模块
import {
reactive, onMounted } from 'vue'
import http from '@/utils/request'
let parmar = reactive({
menus: [
]
});
onMounted(() => {
getData()
})
const getData = async () => {
let {
data } = await http.get('/menus');
// 这里直接赋值对象里面的数据,就不会造成把响应式替换掉的情况了,直接在页面上通过parmar.menus使用数据!
parmar.menus = data.data;
console.log( parmar);
}
</script>
Using this approach, the data is also reactive.
3. The for of loop pushes to the reactive data without destroying the data structure
code show as below:
<script setup>
// 引入模块
import {
reactive, onMounted } from 'vue'
import http from '@/utils/request'
let menusList = reactive([])
onMounted(() => {
getData()
})
const getData = async () => {
let {
data } = await http.get('/menus');
for (let i of data.data){
menusList.push(i);
}
console.log(menusList);
}
</script>
Summarize
The main problem is to use
reactive
the generated responsive data and响应式数据
replace it with the value in the direct assignment普通数据
, resulting无法监听数据
in changes.