1.vue3中reactive定义的引用类型直接赋值导致数据失去响应式

  • 这里写的很详细,想看可以看看@地址,我这里说下结果就可以~
  • reactive定义的数组或者对象,不能直接对整体进行赋值修改,否则定义的数据将失去响应性。

失去响应式示例

  • 当经过一秒后,页面显示的内容并没有被改变!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div style="border: 1px solid red" class="content">
{{ banner }}
</div>
</template>

<script>
import { reactive, onMounted } from "vue";
export default {
name: "HomeView",
components: {},
setup() {
//预先定义一个数据填充占位
var banner = reactive({});
onMounted(() => {
setTimeout(() => {
banner = { name: "李白", age: "18" };
console.log("修改值完成");
}, 2000);
});

return {
banner,
};
},
};
</script>

2.vue使用插槽的简写和使用默认插槽

使用插槽简写v-slot直接用字符’#’代替

  • 使用Navbar组件当中的默认插槽 v-slot:default等同于#default
1
2
3
<Navbar>
<template #default> 商品分类 </template>
</Navbar>

3.flex:1是什么意思在弹性布局当中

  • flex属性是以下三个属性的简写(用于弹性元素-也就是父元素被设置了display:flex,然后子元素就可以设置flex属性)

    • flex-grow :设置增长系数(也就是如何分配剩余的空闲空间) 如果元素不是弹性盒对象的元素,则 flex-grow 属性不起作用。
    • flex-shrink :设置收缩系数
    • flex-basis:设置基准值
  • 当我们设置为flex:1的时候,相当于设置了 flex:1 1 0 也就是设置了flex-grow,其他都设置默认值

  • 经常用来设置元素不管其内容如何,使所有弹性项目的长度均相同

  • 具体可以看看MdnWeb @flex属性

4.vue3使用编程式导航

  • vue2的时候,编程式导航都是通过this.$router.push等方法来进行的,但是到了vue3,是没有this了~

vue3使用编程式导航和获取当前路由对象

  • 首先导入

    1
    2
    3
    4
    5
    //为了获取路由总管 --- 注意,这里有字母r
    import {useRouter} from "vue-router";

    //为了获取当前自身路由信息 --- 注意,这里没有字母r
    import {useRoute} from "vue-router";
  • setup当中调用useRouter方法获取路由总管 和调用useRoute方法获取自身路由信息

    • const router = useRouter(); 这样子就相当于vue2时候的this.$router
    • const route = useRouter(); 这样子就相当于vue2时候的this.$route
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { useRouter, useRoute } from "vue-router";
export default {
name: "HomeView",
components: {},
setup() {
//路由总管
const router = useRouter();
//自身路由
const route = useRoute();
//输出查看
console.log(route);
//编程式导航
function clickTo() {
router.push({ path: "/about" });
}
return { clickTo };
},
};

5.设置超出容器内容隐藏并添加省略号

  • 设置overflow:hidden white-space:nowrap text-overflow:ellipsis

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>超出部分添加省略号</title>
<style>
*{
margin:0;
padding: 0;
}
#over{
/* 设置下位置 */
margin: 20px auto;
width: 200px;
height: 40px;
border: 1px solid red;
/* 查出隐藏 */
overflow: hidden;
text-overflow: ellipsis;/* 文本超出省略号 */
white-space: nowrap;/* 连续的空白符会被合并。但文本内的换行无效 */
}
</style>
</head>
<body>
<div id="over">
<span>我认为, 文森特·皮尔说过一句富有哲理的话,改变你的想法,你就改变了自己的世界。这不禁令我深思。 的发生,到底需要如何做到,不的发生,又会如何产生。 的发生,到底需要如何做到,不的发生,又会如何产生。 这样看来, 佚名说过一句富有哲理的话,感激每一个新的挑战,因为它会锻造你的意志和品格。这似乎解答了我的疑惑。 要想清楚,,到底是一种怎么样的存在。 总结的来说, 培根曾经说过,合理安排时间,就等于节约时间。这不禁令我深思。</span>
</div>

</body>
</html>

6.vue3的ref来获取dom元素

  • 1.元素添加ref属性
    • 比如<div ref="content">我是内容</div>
  • 2.setup当中添加const 刚刚添加的ref属性名称 = ref(null)
    • const content = ref(null) 注意,变量名字必须要和ref属性名字一样!
  • 3.通过setup返回,然后就可以在其他当中调用了
  • 注意
    • 需要在return当中返回
    • 需要添加.value才可以正确获取到dom节点(因为返回的是引用示例,所以需要在访问一层才可以)

示例代码

  • 通过ref来读取属性并输出里面的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div style="border: 1px solid red" ref="content">我是动感超人</div>
</template>

<script>
import { onMounted } from "vue";
import { ref } from "vue";
export default {
name: "HomeView",
components: {},
setup() {
const content = ref(null);
onMounted(() => {
//输出'我是动感超人'
console.log(content.value.textContent);
});
return {
content,
};
},
};
</script>

7.getBoundingClientRect

功能

示例说明

  • 主要关注#box的样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<style>
#box {
width: 400px;
height: 200px;
padding: 20px;
margin: 50px auto;
background: purple;
}
</style>
<div id="box"></div>
<script>
var object = document.querySelector("#box");
var objectDomInfo = object.getBoundingClientRect();
console.log(objectDomInfo);
</script>

</body>

</html>
  • getBoundingClientRect返回对象的属性
1
2
3
4
5
6
7
8
bottom: 290
height: 240
left: 539.6000366210938
right: 979.6000366210938
top: 50
width: 440
x: 539.6000366210938
y: 50
  • getBoundingClientRect返回对象的属性说明

    • x: /left: 元素左上角顶点相当于当前浏览器视口的左边距离

    • y: /top:元素左上角顶点相对于当年浏览器视口的顶部距离


    • width:400+20+20 = 440 (width+padding-left+padding-right)

      • 当前元素的width+paddin-left+padding-right的值
    • height:200+20+20 = 240 (height+padding-top+padding-bottom)

      • 当前元素的height+padding-top+padding-bottom的值
    • 注意点:

      • width/height 是与元素的 width/height + padding 相等的。

    • bottom:元素右下角顶点相对于当年浏览器视口顶部的距离

    • right:元素右下角顶点相对于当年浏览器视口的左边的距离

8.better-scroll

  • @中文文档

  • 安装

    1
    npm install better-scroll --save
  • 引入

    1
    import BetterScroll from "better-scroll";
  • 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import BetterScroll from "better-scroll";
import throttle from "lodash/throttle";
import debounce from "lodash/debounce";
setup(){
//一般在dom结构创建完成后调用
onMounted(()=>{
// 创建BetterScroll对象
bs = new BetterScroll(".home-wrapper", {
probeType: 3,
click: true,
pullUpLoad: true,
});
})
//添加滚动事件,使用下节流阀
bs.on(
"scroll",
throttle((position) => {
//position.y可以获取滚动距离
}, 100)
);
//当拉动到底部的时候
bs.on(
"pullingUp",
throttle(() => {
console.log("到底部了");
//发送ajax请求获取新页

//....

//完成上划动作
bs.finishPullUp();
bs.refresh();
}, 80)
);

}

9.手机端常用的左边分类,上部标签页,右部分布局页的结构代码

效果图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<template>
<div>
<Navbar>
<template #default> 商品分类 </template>
</Navbar>
<div class="category-wrapper">
<!-- 排序分布栏 -->
<div class="navbar">
1
</div>
<!-- 左侧分类列表 -->
<div class="left-list">2</div>
<!-- 书籍展示 -->
<div class="show-list">3</div>
</div>
</div>
</template>

<script>
import Navbar from "@/components/common/navbar/Navbar";
export default {
name: "Category",
components: {
Navbar,
},
};
</script>

<style lang="less" scoped>
.category-wrapper {
//隔开顶部nab
margin-top: 45px;
display: flex;
// 为左侧分类列表的宽度
@leftItemWidth: 130px;
//nav的宽度
@navBarHidth: 40px;
.navbar {
background-color: red;
float: right;
position: fixed;
right: 0;
height: @navBarHidth;
left: @leftItemWidth;
z-index: 10;
}
// 左侧分类列表
.left-list {
position: fixed;
width: @leftItemWidth;
left: 0;
height: 100%;
background-color: green;
}
// 书籍展示
.show-list {
background-color: blue;
position: absolute;
right: 0;
// nav的宽度 + 顶部的商品分类宽度
top: @navBarHidth+45;
left:@leftItemWidth;
height: 100%;
}
}
</style>

10.深度选择器vue3

  • 通过:deep(选择器) { .... } 来实现,具体看代码~

  • ::v-deep在vue3被废弃了,不推荐使用,推荐使用:deep()这种方式

示例

  • less代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style lang="less" scoped>
#address {
margin-top: 45px;
.content {
background: white;
:deep(.van-radio__icon) {
display: none;
}
}
:deep(.van-address-list__bottom){
bottom: 50px;
background-color:unset;
}
}
</style>

11.vant组件库van-collapse 下拉折叠面板出现Collapse: “v-model” should not be Array in accordion mode

  • 原因
    • 默认的下拉折叠面板是可以展示多个数据的,所以v-model绑定的是一个数组,但是这里使用了accordion属性,就只记录一个的值,不需要使用到数组,所以就出现这个提示
  • 解决办法
    • v-model=”activeNames”当中的activeNames变量值改为一个基本数据类型即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!-- v-model="activeNames" -->
由于这里使用了只能选中一个,并且这里为什么取名叫activeNames,是记录展开的列表项,但是
但是这里使用了accordion属性,就只记录一个,就没有必要用数组了
<van-collapse v-model="activeNames" accordion>
<!-- title为一级列表的展示名 -->
<van-collapse-item
v-for="(firstLevel, index) in categoryList"
:key="firstLevel.id"
:title="firstLevel.name"
:name="firstLevel.name"
>
<!-- 二级列表 -->
<van-sidebar v-model="active">
<van-sidebar-item
v-for="(secondLevel,index) in firstLevel.children"
:key="secondLevel.id"
:title="secondLevel.name"
/>
</van-sidebar>
</van-collapse-item>
</van-collapse>


setup() {
//左分类默认项
const active = ref(0);
但是这里使用了accordion属性,就只记录一个,就没有必要用数组了
//const activeNames = ref([]);
const activeNames = ref();//这样子就可以

const categoryList = ref([]);
onMounted(async () => {
let result = await reqCategory();
//保存存储数据
categoryList.value = result.categories;
});
return {
active,
activeNames,
categoryList,
};
},

14.vant组件库sidebar(侧边导航) 和 Collapse(折叠面板)的结合使用

效果:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!-- 左侧分类列表 -->
<div class="left-list">
<div class="left-item-content">

<van-sidebar v-model="activeSecond">
<!-- 当做一个整体 -->
<van-collapse v-model="activeName" accordion>
<!-- 循环一级菜单 -->
<van-collapse-item
v-for="item in categoryList"
:key="item.id"
:title="item.name"
:name="item.name">

<!-- 循环二级菜单 -->
<van-sidebar-item
v-for="sub in item.children"
:title="sub.name"
:key="sub.id"/>

</van-collapse-item>
</van-collapse>
</van-sidebar>
</div>
</div>
setup当中内容
import { ref } from "vue";
export default {
name: "HomeView",
components: {},
setup() {
//设置为99999,就不会出现初始化的时候单击任意一级菜单看到二级菜单选中的情况了
const activeSecond = ref(99999); //二级分类列表目前活动项
const categoryList = ref([]); //左侧分类列表
const activeName = ref(); //一级分类列表的活动项记录
return {
activeSecond,
categoryList,
activeName
};
},
};

12.linear-gradient的知识点

linear-gradient确认起点和终点

  • linear-gradient线性渐变是通过一个定义的,这个轴称为渐变轴/渐变线。如图,红色的为渐变轴/渐变线,正方形的为div容器示例

  • 轴通过顺时针旋转来进行设置起点和终点

    • 设置完成起点和终点后,将颜色进行分布(如果没有对颜色位置进行分布,则平均分配颜色位置)
  • linear-gradient默认方向为to bottom

linear-gradient常见的绘制方向的坐标轴和效果示例

  • to top, to bottom, to leftto right 这些值会被转换成角度 0 度、180 度、270 度和 90 度。
  • 简单理解方向
    • to 指明终点渲染的方向

1.background-image:linear-gradient(red, green);

  • 默认情况轴被旋转了180度
  • 等同于linear-gradient(to bottom,red,green)
  • 默认值to bottom转化为180度

background-image:linear-gradient(red, green)

2.background-image: linear-gradient(to top,red,green);

  • 轴没有被旋转的情况
  • 0度

background-image: linear-gradient(to top,red,green)

3.background-image: linear-gradient(to left,red,green);

  • 轴被旋转270度的情况
  • 270 度

background-image: linear-gradient(to left,red,green)

4.background-image: linear-gradient(to right, red,green);

  • 轴被旋转90度的情况
  • 90度

background-image: linear-gradient(to right, red,green)

5.background-image: linear-gradient(45deg, red,green);

  • 轴被旋转45度的情况
  • 45度

6.示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

<div id="div1">
div1
</div>
<div id="div2">
div2
</div>
<div id="div3">
div3
</div>
<div id="div4">
div4
</div>
<div id="div5">
div5
</div>
<style>
#div1,#div2,#div3,#div4,#div5{
float: left;
width: 200px;
height: 200px;
margin: 10px 5px;
}
/* 指定渐变线,默认是to bottom */
/* to top, to bottom, to left 和 to right
这些值会被转换成角度 0 度、180 度、270 度和 90 度。
其余值会被转换为一个以向顶部中央方向为起点顺时针旋转的角度。渐变线的结束点与其起点中心对称。 */
#div1{
/* 等同于linear-gradient(to bottom,red,green),轴旋转了180度 */
background-image:linear-gradient(red, green);
}
#div2{
/* 轴旋转了0度 */
background-image: linear-gradient(to top,red,green);
}
#div3{
/* 轴旋转了270度 */
background-image: linear-gradient(to left,red,green);
}
#div4{
/* 轴旋转了90度 */
background-image: linear-gradient(to right, red,green);
}
#div5{
/* 轴被旋转45度的情况 */
background-image: linear-gradient(45deg, red,green);
}
</style>
</body>
</html>

linear-gradient颜色绘制参数理解

  • 就是渐变轴上颜色分布情况,和ps有些类似

示例

  • linear-gradient(0deg, blue, green 40%, red);
  • 从下到上,从蓝色开始渐变、到高度40%位置是绿色渐变开始、最后以红色结束
  • 演示结构图

  • 效果图

13.vant表单验证实现邮箱为空提示信息1,格式不正确提示信息2

  • 看代码就可以,在配置rules的时候,传入多个配置对象
1
2
3
4
5
6
7
8
9
10
11
<van-field
autocomplete
v-model="email"
type="text"
label="电子邮箱"
name="pattern"
placeholder="请输入邮件"
:rules="[
//为空提示这个
{ required: true, message: '请填写您的邮箱!' }, //正则出错提示这个
{ pattern: /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/, message: '邮箱格式错误!'}]" />

14.vant组件库Toast轻提示全局注册没有用并且样式丢失了

  • 解决:原来的全局注册换成哪里用到就引入

    • import {Toast} from "vant";
  • 样式丢失错误

  • 解决错误

    • 引入样式,我们需要使用哪个组件,就引入哪个组件样式即可,比如我们只使用按钮组件,则只需要引入按钮样式,如下:
    • import 'vant/lib/toast/style'

15.vue3.x组件当中和js当中使用vuex

  • 组件当中(.vue)

    • 引入import {useStore} from "Vuex";
    • 然后调用useStore返回的值相当于vue2.x时候的this.$store
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import { useStore } from "vuex";
    export default {
    name: "HomeView",
    components: {},
    setup() {
    //使用vuex仓库,等同于vue时候的this.$store
    const store = useStore();
    //获取 Authorization 当中的值
    console.log(store.state.Authorization);
    return {

    };
    },
    };
  • js当中使用

    • 首先引入import store from "@store/index.js"
    • 然后这个store相当于vue2时候的的this.$store

16.vant的Toast(轻提示)设置不自动关闭,后面手动关闭

  • vant的回答解决办法 @地址 也就下面这种方法
  • 通过设置配置对象当中的duration:0 即可
1
Toast.loading({message:"正在加载...",forbidClick:true,duration:0})
  • 然后后面可以调用Toast.clear()来关闭提示

17.window.localStorage.getItem获取不到指定的key值,返回的是null而不是undefined

18.vue3使用keep-alive路由缓存保活

添加路由缓存/保活

  • 1.在需要缓存的路由组件添加元信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/',
name: "Home",
component: Home,
meta: {
title: "梦洁小站-图书兄弟",
keepAlive: true, // 组件需要缓存
},
},
]
  • 2.App.vue原来的<router-view></router-view>删除
  • 3.App.vue更换为如下代码的路由组件
1
2
3
4
5
6
7
8
<router-view v-slot="{ Component }">
<transition>
<!-- includeList变量需要通过setup返回 -->
<keep-alive :include="includeList" :key="Component">
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
  • 4.App.vue组件当中添加如下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { onMounted, toRefs, reactive, watch } from "vue";
import {useRoute} from "vue-router";
export default {
name: "App",
setup() {
const route = useRoute();
//设置需要缓存的路由组件
const state = reactive({
includeList: [],
});
onMounted(() => {
//监视路由的改变,如果改变了,则添加进入路由组件
watch(() => route,(newVal,oldVal)=>{
//读取当前路由组件的元数据,看是否有KeepAlive并且为true
//并且在缓存列表includeList当中不存在当前组件才添加进入缓存组件
if(newVal.meta.keepAlive && state.includeList.indexOf(newVal.name) === -1){
state.includeList.push(newVal.name);
}
},{deep:true}) // 开启深度监听,不然没有效果
return {
//提供给`router-view`组件使用变量名
...toRefs(state),
};
},
};

使用失效的问题

  • 我发现是vue-router当中index.js当中的name属性vue组件当中的name值不匹配导致的,改为相同就可以

  • 还有就是,name属性名称第一个字母大写…(为了迎合组件当中name属性的写法)之前我一直小写的

  • 其他失效可以看看这个博客 @vue 的 keep-alive include 属性不生效问题

19.vue3项目本地热更新时报错TypeError: parentComponent.ctx.deactivate is not a function

报错信息

  • 解决方法: 在keep-alive、component上设置key进行排序(即加个key)

  • 改之前的代码会报这个错

1
2
3
4
5
6
7
<router-view v-slot="{ Component }">
<transition>
<keep-alive :include="includeList" >
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
  • 改之后,添加key
1
2
3
4
5
6
7
<router-view v-slot="{ Component }">
<transition>
<keep-alive :include="includeList" :key="Component">
<component :is="Component" />
</keep-alive>
</transition>
</router-view>