距离vue3出来也是有段时间了,用它做了一个项目,本文简单总结一下使用vue3日常开发遇到的问题,和之前变动还是蛮大的
transition组件
vue2.x中使用路由的过渡组件直接使用就ok,在vue3的版本中,要使用router-view
进行包裹,就像下面这样,不然没效果,控制台也会有警告
全局相关
3.x的版本中,挂载全局使用globalProperties
,详情可以去看官方文档;比如下面我们一个全局的请求地址
import { httpUrl } from '@utils/config.js'
const app = createApp(App)
app.config.globalProperties.$httpUrl = httpUrl
app.use(router)
.use(store)
.use(elementPlusUI)
.mount('#app')
要使用就要借助defineComponent
和getCurrentInstance
来获取
import { toRefs, reactive, defineComponent, getCurrentInstance } from "vue"
export default defineComponent({
setup() {
const {appContext: {config:{ globalProperties: common }}} = getCurrentInstance()
const state = reactive({
routes: [
{
menuName: "仪表盘",
path: "/analysis",
name: "analysis",
},
]
})
//点击菜单
const handleSelect = (key) => {
console.log(common)
common.$router.push(key)
}
return {
...toRefs(state),
handleSelect,
}
}
})
同理,监听路由也是
import { reactive, toRefs, watch, defineComponent, getCurrentInstance } from "vue"
export default defineComponent({
const {appContext: {config: {globalProperties: ctx}}} = getCurrentInstance()
watch(
() => ctx.$route,
(newVal,old) => {
const breads = {
...generateBreadByRoutes(routes.options.routes[0]),
'/': '首页'
}
state.routes = getBreadcrumbs(breads, newVal.path)
},
{ immediate: true }
)
return {
watch
}
})
组件相关
1、异步组件
import { defineAsyncComponent } from 'vue'
export default {
components: {
comMenu: defineAsyncComponent(() => import('@components/menu')),
comHeader: defineAsyncComponent(() => import('@components/header')),
breadcrumb: defineAsyncComponent(() => import('@components/breadcrumb'))
},
setup() {
}
}
2、父子组件传值(主要介绍$emit,on的用法和emit都相差不大)
父组件中引入组件
<script>
import { reactive, toRefs, defineAsyncComponent } from 'vue'
export default {
components: {
tableDemo: defineAsyncComponent(() => import('./component/table.vue'))
},
setup(_, context) {
const state = reactive({
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
})
const observerInfo = (e) => {
console.log('子组件传来的数据为',e)
}
return {
...toRefs(state),
observerInfo
}
}
}
</script>
在子组件中,需要在setup中获取到上下文的对象,因为emit是在这里面的
export default {
props: ['tableData'],
setup(_, context) {
const handleClick = (row) => {
console.log('context----------------------',context)
context.emit('deliverInfo', row)
}
return {
handleClick
}
}
}
vue3结合ElementUI Plus
我的项目是使用脚手架搭建的,没有使用vite,所以下面主要是脚手架的配置
安装完成后,运行:npm install element-plus --save
安装 element-plus
安装成功后,在main.js引入其他相关的文件
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import router from './router/index'
import './router/permission'
import '../src/assets/css/index.css'
import '../src/assets/css/transitions.css'
import '@components/progress.js'
import { httpUrl } from '@utils/config.js'
import elementPlusUI from '../elementPlusUI'
const app = createApp(App)
app.config.globalProperties.$httpUrl = httpUrl
app.use(router)
.use(store)
.use(elementPlusUI)
.mount('#app')
安装完babel后进行配置babel,根目录新建babel.config.js进行配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
elementPlusUI.js代码,因为引入的组件的太多了,我单独抽离写出来了,只写部分
import {
ElContainer, ElAside, ElMenu, ElMenuItemGroup, ElDropdown, ElDropdownItem,
} from 'element-plus'
export default (app) => {
//挂载全局message弹窗信息
app.config.globalProperties.$message = ElMessage
app.use(ElContainer)
.use(ElAside)
.use(ElMenu)
.use(ElDropdownMenu)
.use(ElDropdownItem)
.use(ElMenuItemGroup)
.use(ElBreadcrumbItem)
}
v-for优化建议
假如后台返回的数据有几千个,但是只有 3 个需要渲染。那么每次重新渲染时,即使 这3 个数据根本没有变化,vue 也必须遍历几千个项目。所以应该尽量避免这种情况,那么我们可以使用计算属性或者使用过滤方法
<el-table
:data="data"
stripe
style="width: 100%" />
import { toRefs, reactive, computed } from "vue"
export default {
setup() {
const state = reactive({
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
})
//一个可读可写的计算属性
const data = computed({
get() {
return state.tableData
},
set(value) {
return state.tableData = value
}
})
}
}