/*
提高首屏加载速度
import xx from 'xxx'
1 引用模块化 使用 import('xxx') 函数 返回 promise
打包 在 除了 app.js vender.js 之外的 chunk.hash.js 中
使用时加载 懒加载
2 vue 文件 使用 异步组件 包裹
父组件 导入 defineAsyncComponent 接收一个函数
const AsyncAbout = defineAsyncComponent(() => import('xxxx/AsyncAbout.vue'))
<AsyncAbout> </AsyncAbout>
这样 就会单独打包--chunk.hash.js
写法二
defineAsyncComponent({
loader:() => import('xxxx/AsyncAbout.vue')
loadingComponent:Loading.vue // 占位组件
errorComponent:error.vue // 加载失败 展示
delay:2000 // loadingComponent 之前等待多久
onError:(err,retry,fail,attempts)=>{
1 错误信息
2 retry 函数 调用重试
4 重试次数记录
}
})
结合 suspense 包裹
<suspense>
<template #default>
<AsyncAbout/>
</template>
<template #fallback>
<Loading/>
</template>
</suspense>
获取根组件 父组件
$root $parent
dom自身传递 数据 获取 data-语法
:data-index = "xxx"
dom.dataset.index 即可取出来
MixIn
export demoMixIn = {
data:
methods:
}
mixins:[demoMixIn]
重名
data
methods 就近原则,以组件为准
生命周期 合并在数组中 都会执行
全局混入 混入 所有组件中
app.mixin(demoMixIn)
watch
const stop = watchEffect()
合适的时机
stop() 可以停止监听
age变化很快 api调用没有完成 但是每次变化都会触发 api
这里消除 副作用 取消没有完成的 api 根据 age变化 发送 最新的 api
watchEffect((onInvalidate)=>{
// 变化 和 组件销毁 优先执行 onInvalidate函数
onInvalidate(()=>{
request.cancel()
})
age
axios
},{
flush:'pre' // pre 提前执行 post dom挂载完毕执行
})
单向数据流 子组件获得响应数据 但是不可更改 可以发emit 数据源更改
provide('name',readonly(ref(1)))
render 函数 === js { }
template(div)-->编译-->render-->VNode-->div
可以自己写 render -->借助 h-->VNode-->div
render 函数 返回 VNode
h函数 返回 VNode
所以
render(){
return h()
}
div 属性 内容或者子元素
h(参数1|参数2|参数3){
}
h函数 第三个参数 可以传递 插槽 default是一个函数 返回 h 函数
子组件中
render(){
return h('div',null,[
h('span',null,'我是span')
slots.default ? slots.default({name:'作用域插槽的传值实现方式'}) : h('span',null,'没有插槽时默认显示我')
])
}
父组件中
import 子组件 from 'xxx'
render(){
return
h(子组件,null,{
default:props=>h(‘span’,null,`${props.name}`)
})
}
https://gitee.com/wang-kotlin/fresh-rabbit/blob/master/src/components/library/XtxBread.vue
jsx = h 返回 VNode
render(){
return <div class='xxx'>我是jsx</div>
}
子组件
render(){
return <div>
<h2>我是子组件</h2>
{ slots.default ? slots.default({name:'作用域插槽的传值实现方式'}) : <span>没有插槽时默认显示我</span> }
</div>
}
父组件
render(){
return <son-component>
{ { default:props=><button>{props.name}</button> } }
</son-component>
}
// render(虚拟节点,容器)--> 生成 真实DOM
import { render } from 'vue'
const vDiv = <div class="confirm-container"></div>
// 虚拟节点(h(),jsx) 真实DOM--容器
render(vDiv, document.body)// 真实DOM
const vNode = <span></span>
// vNode.el 属性可以看到真的的 DOM===document.XXX
render(vNode, vDiv.el)// 真实DOM
asp/jsp/php 后端开发页面 后端路由
vue-router
默认class
1 默认 router-link-active
.router-link-active{ }
修改 <router-link active-class='xxx'>
全局修改
linkActiveClass=''
linkExactActiveClass=''
.xxx{ }
当前路由 /home/goods
<router-link to='/home' exact-active-class='xxx' />
/home router-link-active
<router-link to='/home/goods' />
/home/goods router-link-active router-link-exact-active
懒加载 component:()=>import('xxxx')
dist 分包 但是没有名字 chunk-hash.js
魔法注释 -- 加名字 -- home-chunk-hash.js
*/
// component:()=>import(/* webpackChunkName: "home-chunk" */ 'xxxx')
/*
路由匹配
一般来说,我们把404路由定义在最后
{
path: '/:pathMatch(.*)*',
name: 'notFound',
component: () => import('./views/404'),
},
进入没定义过的路由,我们都会给他显示404页面
http://localhost/:8081/Ling
http://localhost/:8081/Ling/ha
pathMatch(.*) 为 string
route.params.pathMatch === 'Ling/ha'
pathMatch(.*)*--route.params.pathMatch为数组
route.params.pathMatch ====['ling'] ['ling','ha']
以特定字符串开头的路由匹配
{
path: '/member:id(.*)',
component: () => import('./views/member'),
name: 'member',
},
http://localhost:8081/member
http://localhost:8081/member01 -- route.params.id 01
<router-link to='/home' v-slot="{ href,route,navigate,isActive,isExactActive }" custom>
<div>
</router-link>
移除 tag='div'
其他元素 或者 组件以插槽的形式 插入 外面包裹 a
作用域插槽 传递过来的 属性
href url
route route
navigate 导航函数
isActive,isExactActive boolean 是否匹配 精准匹配
custom 添加后 外层 a 去掉 点击无法 跳转 可以 使用 οnclick='navigate' 实现
router-view
作用域插槽 缓存 与 动画
<router-view v-slot="{ Component }">
<keep-alive> or transition
<component :is="Component" />
</keep-alive>
</router-view>
添加路由
1 直接添加
router.addRoute({})
2 添加子路由 name--father
router.addRoute('name',{})
删除路由
1 添加 name 相同的 替换
2 router.removeRoute('name')
3 const remove = router.addRoute('name')
remove() 删除路由
router.hasRoute() boolean
router.getRoutes() []
router.beforeEach((to, from) => {
无 next
1 return false 不导航
2 return undefined 或者 不写 原计划 导航 next()
3 return ‘/home’
4 return { path:'/home' }
})
数据改变是 同步代码 for (i=0; i<100; i++) { counter.value ++ }
watch
nextTick
等 是 微任务 等 数据同步完成 最后 微任务 执行一次回调即可
history 后端 nginx 解决 刷新 携带数据问题
nginx 配置 try_files /index.html xxxx/home 找不到 最后返回 index.html
location / {
root /user/local/docker/web/gzfsweb/;
# vue router history 模式
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
*/
// vite 动态 组件导入 使用 Glob 导入 多层级文件 双 *
// const modules = import.meta.glob('@/views/**/*.vue')
/*
modules 为一个对象 Key value
/src/views/user/Login.vue: () => import("/src/views/user/Login.vue?t=1678156663870")
通过 key 取值
const component = modules[`/src/components/${item.component}.vue`]
vue3 笔记 补充-h函数-VNode-vite-动态路由
于 2023-04-19 15:23:05 首次发布