[TOC]
初始化项目
npm init vite
一个字
sfc 单文件组件
遇到的问题:
- 开发依赖一定要放到 devDependencies
- 404 匹配
{
path: "/:catchAll(.*)", // 不识别的path自动匹配404
redirect: '/404',
},
原因:Vue Router不再使用path-to-regexp,而是实现了自己的解析系统,该系统允许路由排名并启用动态路由。由于我们通常会在每个项目中添加一条单独的包罗万象的路线,因此支持的特殊语法没有太大的好处*。参数的编码是跨路线编码,无一例外使事情更容易预测。
更好的封装,把一套逻辑封装到一个函数内,利于程序解耦 脚本标签上加上setup属性 标签内的脚本就可以使用
<script setup lang="ts">
import { ref,onMounted,onBeforeUpdate,reactive, onUnmounted, toRefs, watch, computed } from "vue";
// props的使用
let props = defineProps<{ msg: string }>();
console.log(props);
// 创建响应式数据
const count = ref(0);
const age = ref(0);
// 每个函数都可以注册生命周期函数
function useMousePosition () {
const position = reactive({
x: 0,
y: 0
})
const update = (e:MouseEvent) => {
position.x = e.pageX
position.y = e.pageY
}
watch(position,()=>{
console.log('position:update')
})
// 计算属性返回的是一个响应式数据
const cmp = computed(()=>{
return position.x + position.y
})
onMounted(() => {
window.addEventListener('mousemove', update)
})
onBeforeUpdate(()=>{
console.log('useMousePosition:update')
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
// 在需要解构的场景需要将对象用toRefs包装一下
return toRefs({
cmp,
...toRefs(position)
})
}
const { x, y, cmp } = useMousePosition()
</script>
vuex 在 setup函数内使用 mapActions mapMutations 直接返回映射后的函数会报错,报错大概是在:
var dispatch = this.$store.dispatch;// this 是undefined
解决办法:
const { numAction } = mapActions(['numAction'])
strMutation:strMutation.bind({ $store: store }),
• 开启 flex 布局使用display: flex属性。
• flex 布局有主轴和交叉轴,分别使用justify-content和align-items控制对齐方式。
- justify-content: flex-start|center|flex-end|space-between|space-evenly|space-around;
对应轴上的对齐方式
-align-items: stretch(拉伸)|flex-start(轴向开始)|center(轴向居中)|flex-end | baseline (文字基线)|align-content
• 支持按行或列进行排列,使用flex-direction,另外也支持row-reverse和column-reverse反向排列。
• -flex-direction: column(行模式)| row(列模式)| *-reverse (对应模式的逆序)
• 子元素可以通过flex简写形式,或者flex-grow,flex-shrink,flex-basis 来调整元素的空间占比和缩放。
-flex-basis 设置主轴方向为固定值
-flex-grow 这个属性是说 flex 容器在有剩余空间的时候,子元素占据剩余空间的占比。
-flex-shrink当它们的宽度超过 flex 容器之后,该如何进行收缩
• 通过flex-wrap可以设置 flex 子元素折行显示。
• 嵌套flex容器的缩放问题。
作者:峰华
链接:https://juejin.cn/post/6844904116141948936
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
function getBreadList() {
let list:RouteLocationMatched[] = reactive([])
const route = useRoute()
watch(route,()=>{
let matched = route.matched;
//如果不是首页
if (matched.length && !isHome(matched[0])) {
matched = ([{ path: "/", meta: { title: "首页" } }] as unknown as RouteLocationMatched[]).concat(matched);
}
list.length = 0;
matched.forEach(item=>list.push(item))
},{immediate:true})
return list
}
//在 <script setup>内使用
<template>
<el-form ref="form" label-width="120px">
<el-form-item label="名称">
<el-input v-model="name"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input v-model="age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
<el-button>Cancel</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts" setup>
import { reactive, toRefs,ref } from 'vue'
function getForm () {
const form = reactive({
name:'',
age: 0,
})
return toRefs(form)
}
const { name, age } = getForm();
const onSubmit = function() {
console.log('submit!',name.value,age.value)
}
</script>
//在普通<script>内使用
<template>
<el-input v-model="input" placeholder="Please input" />
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
return {
input: ref(''),// 对象需要toRefs转换
}
},
})
</script>
<-- 跟随鼠标移动 >
<div class="postion" :style="{top:y+'px',left:x+'px'}"></div>
const update = (e:MouseEvent) => {
position.x = e.pageX -150
position.y = e.pageY -150
}
.postion {
width: 100px;
height: 100px;
background-color: blue;
position: fixed;
/* 旋转动画 */
animation:turn 1s linear infinite;
/* 旋转偏移 */
transform-origin:150% 150%;
}
@keyframes turn{
0%{
transform:rotate(0deg);
}
25%{
transform:rotate(90deg);
}
50%{
transform:rotate(180deg);
}
75%{
transform:rotate(270deg);
}
100%{
transform:rotate(360deg);
}
}
li:nth-child(n) n = int / even odd 如果最后一个/第一个不是li则不选择任何元素(助记:选中第一(n)个/最后一(n)个,前面的条件符合则选中,否则不选中)
li:nth-of-type()n = int / even odd 有li则选中最后一个/第一个(助记:选中第一(n)个/最后一(n)个并且符合前面条件的元素)
可以在选项API中声明setup函数,也可以在script标签上添加setup属性,脚本内所处的就是setup环境,这里所处的生命周期相当于vue2的created,这里没有this,建议要符合函数式编程思想来编写逻辑,一切都是函数,每组逻辑的状态都是在函数内进行维护
ref reactive toRefs
ref 是对单值进行响应化操作,通过xxx.value的方式对值进行取值赋值的操作,使其拥有响应式能力
reactive 是对对象类型的数据进行响应化的操作,包括一般对象及数组进行包装,但是不能对其进行解构操作,这将失去响应式,此时可以对其进行toRefs操作,使其浅层属性进行ref包装,在解构时不会丢失响应式能力,在混合多个对象时也应该使用该方式。
-
v-enter-from:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
-
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
-
v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡/动画完成之后移除。
-
v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
-
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
-
v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被移除),在过渡/动画完成之后移除。
<transition name="component-fade" mode="out-in">
<component :is="allComponent[curComponent]"></component>
</transition>
<transition-group name="list" tag="p">
<span v-for="item in items" :key="item" class="list-item">
{{ item }}
</span>
</transition-group>
name: 动态生成class前缀
mode: out-in in-out 先出后进 先进后出 为空时同时进行(transition-group 无效) 更多属性见官方文档: https://v3.cn.vuejs.org/api/built-in-components.html#transition
- 对于高版本浏览器支持但是低版本浏览器不支持的属性,在不影响基本功能和版式的基础上可以放弃某些效果
- 利用属性值的语法差异实现兼容
.icon-loading {
display: inline-block;
width: 30px;height: 30px;
background: url(../../../assets/loading.gif);
background: url(../../../assets/loading.png), linear-gradient(transparent,transparent);
animation: spin 1s linear infinite;
}
- 借助伪类或伪元素区分浏览器
- @supports规则
<var>=<declaration> | <supports-condition>
@supports (animation: none) {
.icon-loading {
background: url(../../../assets/loading.png);
animation: spin 1s linear infinite;
}
}
本组件内引入本组件需要定义名称
export default defineComponent({
name:'tree-item'
})
// 使用路由传入props 需要在这定义props
const props = defineProps({
tabsName:{
type: String,
required: true
}
})
// 解构需要转ref
const { tabsName } = toRefs(props)
// 需要watch这个props
watch(tabsName,()=>{
console.log(tabsName.value)
list.length = 0;
getPage(tabsName.value)
})
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
router.push({
name:'cnode-topic',
params:{
id:item.id
}
})
console.log(route.meta);
<template>
<div class="app">
<div class="box" >
<div class="box1"
:style="{height : isTrue ? '200px':'auto'}"
@click="clickButton"
>
box1
</div>
<div class="box2">box2</div>
</div>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
isTrue:true
}
},
methods:{
clickButton(){
this.isTrue = ! this.isTrue
}
}
}
</script>
<style lang="less" scoped>
.box{
display: flex;
width: 100%;
/*height: 100%;*/
height: 100vh;
flex-direction: column;
background-color: yellow;
.box1{
width: 100%;
background-color:deeppink;
}
.box2{
width: 100%;
flex: auto;
background-color: green;
}
}
</style>
- 父盒子(box)要设置 display: flex; flex-direction: column;前两个固定的 height: 100vh;高度必须设置
- 子盒子1(box1)高度必须是根据条件判断必须包括一个定高,一个auto
- 子盒子2(box2)必须设置flex为auto
组件:swiper,swiper-slide
swiper 是轮播容器 swiper-slide 是轮播的每一个页面
导入:
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from 'swiper/vue';
// Import Swiper styles
import 'swiper/css';
import "swiper/css/effect-cards"
注意:默认导入的是core版本,如果使用其他模块需要导入并安装其他模块功能,包括Autoplay等功能
// import Swiper core and required modules
import SwiperCore, {
EffectCards,
Autoplay
} from 'swiper';
// install Swiper modules
SwiperCore.use([EffectCards,Autoplay]);
样式:
/**
容器样式
*/
.swiper {
...
}
/**
页面样式
*/
.swiper-slide {
...
}
官方简介大意为:正常需要组件树与DOM树是一致的,但是有的情况需要为某个功能增加一个私有的UI组件,但是该组件的真实DOM未必在这个私有组件内部。
例如官方例子里的按钮有个私有的弹窗,但是该弹窗在body下更容易实现,通过声明一个Teleport内置组件,该组件支持一个prop参数to,传入的是一个css选择器,用于指定该组件将被插入到哪个DOM节点中
<template>
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const modalOpen = ref(false)
</script>
<style lang="less" scoped>
.modal {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
background-color: rgba(0,0,0,.5);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 999;
}
.modal div {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: white;
width: 300px;
height: 300px;
padding: 5px;
}
</style>