Skip to main content

moregeek program

vue最佳实践和实用技巧_crmeb中邦科技的博客-多极客编程

1.props限制和透传

​​​内自定义限制

props: {
size: {
// 自定义验证函数
validator: (val) => {
return ["small", "medium", "large"].includes(val);
},
}
}
复制代码

这个验证函数接受一个 prop值,验证并返回 true 或 false
透传属性

<!-- 此组件为二次封装的中间组件 -->
<template>
<MyComponent v-bind="$attrs"/>
</template>

<script>
export default {
// $attrs 中的所有属性不自动继承到组件的根元素上
inheritAttrs: false,
}
</script>
复制代码
  • $attrs包含所有透传过来的对象,除显式声明接受的props、emits、slots
  • 如不希望透传下去某些属性,可使用useAttrs()
const attrs = useAttrs();
const filteredAttrs = computed(() => {
return { ...attrs, style: undefined };
});
复制代码

​$attrs​​还可与listeners`包含了父组件传递的事件(不包含.native修饰器),它可以通过v-on="$listeners"转发传入内部组件,进行对事件的监听处理

<MyComponent v-bind="$attrs" v-on="$listeners" />
复制代码

注意: attrs属性上
单个slot透传

<About>
<template #about>
<slot name="about" />
</template>
</About>
复制代码

多个slot透传

<template #[slotName] v-for="(slot, slotName) in $slots" >
<slot :name="slotName"/>
</template>
复制代码

多个slot透传作用域插槽

<template #[slotName]="slotProps" v-for="(slot, slotName) in $slots" >
<slot :name="slotName" v-bind="slotProps"/>
</template>
<!-- Vue2则需要将v-for里面循环的$slots改成$scopedSlots -->
复制代码

2.require.context()和import.meta.glob()批量引入文件

  • webpack统一导入相同路径下的多个组件的方法
const path = require("path");
// 参数一:说明需要检索的目录,参数二:是否检索子目录,参数三::指定匹配文件名的正则表达式
const files = require.context("./components", false, /\.vue$/);
const modules = {};
files.keys().forEach((key) => {const name = path.basename(key, ".vue");modules[name] = files(key).default || files(key);
});
复制代码
  • Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:
const modules = import.meta.glob('./src/*.js');

// vite 转译上面后生成的代码
const modules = {
'./src/foo.js': () => import('./src/foo.js'),
'./src/bar.js': () => import('./src/bar.js')
}
复制代码

3.有条件的渲染slot

  • 组件都有一个特殊的$slots对象,包含所有的插槽对象,结构如下:
const $slots = {"default": [{...}],"slotA": [{...}],"slotB": [{...}]
}
复制代码

我们可以使用v-if有条件的渲染slot更加合理,并且我们封装通用组件的时候最好预留个slot更好扩展

<template>
<div>
<div v-if="$slots.default">
<slot />
</div>
<div v-if="$slots.slotA">
<slot name="slotA"/>
</div>
</div>
</template>
复制代码

4.检测点击是否发生在元素内部

window.addEventListener('mousedown', e => {
// 获取被点击的元素
const clickedEl = e.target;

// `targetEl` 为检测的元素
if (targetEl.contains(clickedEl)) {
// 在"targetEl"内部点击
} else {
// 在"targetEl"之外点击
}
});
复制代码

5.动态组件和递归组件

动态组件:tab切换的时候可使用动态组件动态加载并缓存提供动效

<transition>
<keep-alive>
<!-- :is值必须是全局或者局部注册过的组件 -->
<component :is="currentTab"></component>
</keep-alive>
</transition>
复制代码

递归组件:模板里面自己自己,注意需要设置条件退出,不然会无限渲染,适合嵌套菜单,树形控件等

<div v-if="item.children">
{{ tree.label }}
<!-- 递归调用自身 -->
<tree v-for="(item, index) in tree.children" :tree="item" :key="index"></tree>
</div>
<script>
export default {
// 定义name,以使组件内部递归调用
name: 'tree',
// 接收外部传入的值
props: {
tree: {
type:Array,
default: () => []
}
}
}
</script>
复制代码

6.nextTick

  • 在下次 DOM 更新循环结束之后执行延迟回调
  • 我们可以在修改数据后立即使用此方法获取最新的DOM
mounted(){
this.$nextTick(() => {
this.$refs.inputs.focus(); //通过 $refs 获取dom 并绑定 focus 方法
})
}
复制代码

7.简化 :class 和 v-if 与逻辑

<div :class="$route.name === 'Home' ||$route.name === 'Gallery' ||$route.name === 'Profile'? 'classOnlyOnThesePages': ''"></div>
复制代码

直接最佳写法如下:

<div :class="{classOnlyOnThesePages: ['Home', 'Gallery', 'Profile'].includes($route.name),}"></div>
复制代码

8.全局重用方法

  • 遇到全局可重用的工具方法,例如
class Utils {// 复制一段文字到剪切板copyToClipboard(text) {let copyText = document.createElement("input");document.body.appendChild(copyText);copyText.value = text;copyText.select();document.execCommand("copy");document.body.removeChild(copyText);}
}

export default new Utils();
复制代码

我们可以抽离出来放在整个应用程序都能访问的地方
Vue2:

import Utils from "./utils/utils.js";
// 设置全局方法
Vue.prototype.$utils = Utils;
复制代码

Vue3:

import Utils from "./utils/utils.js"; 
const app = createApp(App);
// 设置全局方法
app.config.globalProperties.$utils = Utils;
app.mount("#app");
复制代码
接下来任何地方都能愉快的访问啦
this.$utils.copyToClipboard(text);

// Vue3 setup
const { proxy } = getCurrentInstance();
proxy.$utils.copyToClipboard(text);
复制代码

9.局部组件刷新

  • 使用 v-if 方法来控制 router-view 的显示隐藏
<template><div id="app"><router-view v-if="isActive" /></div>
</template>

<script>
export default {name: "App",
// provider给下层组件重刷的方法provide() {return {reload: this.reload,};},data: {
isActive: true,},method: {reload() {this.isActive = false;this.$nextTick(() => {this.isActive = true;});},},
};
</script>
复制代码

需要的页面可注入该方法使用

<script>
export default {inject: ["reload"],methods: {refresh() {this.reload();},},
};
</script>
复制代码

或者直接使用v-if操作该组件

<template><div v-if="isShow"></div>
</template>
<script>
export default {data() {return {isShow: true,};},method: {refresh() {this.isShow = false;this.$nextTick(() => {this.isShow = true;});},},
};
</script>
复制代码

或者借助Vue的diff算法,我们给元素设置一个唯一的Key值然后去改变它

<template><div :key="keyValue"></div>
</template>
<script>
export default {data() {return {keyValue: 0,};},method: {refresh() {this.keyValue++;},},
};
</script>
复制代码

10.组件封装原则

Vue组件的API主要包含三部分:props、event、slot

  • props 为组件接收的参数,最好用对象的写法,可更好设置类型默认值和自定义校验
  • event用于子组件向父组件传递消息
  • slot可以给组件动态插入一些内容或组件,是实现高阶组件的重要途径

组件封装最好还应遵循单向数据流,传递的props仅仅做展示,如需修改,则应该重新初始化一份全新的响应式数据并将props深拷贝后作为初始值

11.错误(警告)处理

为 Vue 中的错误和警告提供自定义处理程序

// Vue 3
const app = createApp(App);
app.config.errorHandler = (err) => {
console.error(err);
};
// Vue 2
Vue.config.errorHandler = (err) => {
console.error(err);
};
复制代码

12.使用template标签分组

template 标签可以在模板内的任何地方使用,可以减少实际嵌套层级,更简化代码逻辑

<template>
<div class="card">
<h3>
{{ title }}
</h3>
<h4 v-if="isShow" class="card-desc">
{{ description }}
</h4>
<div v-if="isShow">
<slot />
</div>
<Home v-if="isShow" />
</div>
</template>
复制代码

上面代码v-if逻辑分组后:

<template>
<div class="card">
<h3>
{{ title }}
</h3>
<template v-if="isShow">
<h4 class="card-desc">
{{ description }}
</h4>
<div>
<slot />
</div>
<Home />
</template>
</div>
</template>
复制代码

13.在 v-for 中解构

在模板中使用 v-for 遍历输出数据,可以使用解构语法

<divv-for="{ id, user } in [{ id: 1, user: 'yun' },{ id: 2, user: 'mu' },]":key="id">{{ user }}
</div>
复制代码

14.全局和局部style混合及样式穿透

<style>
/* 全局有效 */
.content p {
font-size: 12px;
}
</style>

<style scoped>
/* 只在该组件内有效 */
.content {
background: green;
}
</style>
复制代码

有时候我们想跳出scoped这个限定作用域,更改子组件的样式但不会影响全局样式,我们就可以使用深度选择器来完成

<style scoped>
:deep(.ant-card-head-title){
background: green;
}
</style>
复制代码

上面代码会被解析为

[data-v-e44d851a] .ant-card-head-title {
background: green;
}
复制代码

注意:vue版本和预处理不同,深度选择器的写法也会不同,灵活使用即可
15.借用props类型
当我们当前组件使用到了Card组件

<Card :type="Mytype" :color="Mycolor">
复制代码

其中的Mytype和Mycolor是我们通过props接收而来的

import Card from './Card.vue';
export default {
components: { Card },
props: {
Mytype: {
type: String,
required: true,
},
Mycolor: {
type: String,
default: "green",
}
},
};
复制代码

我们可以简写为

import Card from './Card.vue';

const cardProps = {};

Object.entries(Card.props).forEach(([key, value]) => {cardProps[`My${key}`] = value;
});

export default {
components: { Card },
props: {
...cardProps
},
};

完整附件​​点此下载​

©著作权归作者所有:来自51CTO博客作者CRMEB众邦科技的原创作品,请联系作者获取转载授权,否则将追究法律责任

#yyds干货盘点# 前端歌谣的刷题之路-第一百零七题-接口_前端歌谣的博客-多极客编程

 前言我是歌谣 我有个兄弟 巅峰的时候排名c站总榜19 叫前端小歌谣 曾经我花了三年的时间创作了他 现在我要用五年的时间超越他 今天又是接近兄弟的一天人生难免坎坷 大不了从头再来 歌谣的意志是永恒的 放弃很容易 但是坚持一定很酷 本题目源自于牛客网 微信公众号前端小歌谣题目请补全JavaScript代码,完成函数的接口功能。要求如下: 1. 函数接收两种类型的参数,分别为"get?"和"updat

教你开发一个js代码加密工具_mb62456b10a8cef的博客-多极客编程

教你开发一个JS代码加密工具作者:JShaman.com w2sft本文,教你开发一个JS代码加密工具。工具可实现:把正常的JS代码,转化为加密代码,并且加密后的JS代码能直接运行。效果展示加密前的JS代码:function get_copyright(){var domain = "jshaman.com";var from_year = 2017;var copyright = "(c)" +

vue2面试常见面试题收集_wx633fee0815a9a的博客-多极客编程

​Virtual DOM的理解 一、什么是vdom? Virtual DOM 用JS模拟DOM结构 二、为何要用vdom? 1. DOM操作非常非常“rang贵”,将DOM对比操作放在JS层,提高效率 2. DOM结构的对比,放在JS层来做(图灵完备语言:能实现逻辑代码的语言) 三、vdom核心函数有哪些 //核心函数: h('标签名', {...属性名...}, [...子元素...

【web开发】python实现web服务器(sanic)_爱看书的小沐的博客-多极客编程

1、简介 https://sanic.dev/zh/ https://github.com/sanic-org/sanic Sanic 是 Python3.7+ Web 服务器和 Web 框架,旨在提高性能。它允许使用 Python3.5 中添加的 async/await 语法,这使得您的代码有效的避免阻塞从而达到提升响应速度的目的。 目标(Goal) 提供一种简单且快速,集创建和启动于

斐波那契数_安东尼漫长的技术岁月的博客-多极客编程

LeetCode 75 学习计划适用于想为技术面试做准备但不确定应该聚焦于哪些题目的用户。学习计划中的题目都是经过精心挑选的,Level 1和 Level 2 学习计划是为初级用户和中级用户准备的,题目覆盖了大多数中层公司面试时所必需的数据结构和算法,Level 3 学习计划则是为准备面试顶级公司的用户准备的。​​来源​​第 10 天​​斐波那契数​​难度:简单题目斐波那契数 (通常用 F(n)

#yyds干货盘点#慎用json.stringfy_文本、的博客-多极客编程

项目中遇到一个 bug,一个组件为了保留一份 JSON 对象,使用 JSON.stringify 将其转换成字符串,这样做当然是为了避免对象是引用类型造成数据源的污染。但发现后面使用 JSON.parse 方法之后,发现数据有所变化。代码简化:let obj = { name: 'Gopal', age: Infinity}let originObj = JSON.stringify(obj)

vue/js自定义指令:实现元素滑动、移动端适配以及边界处理_qq6310682252356的博客-多极客编程

​​§​​核心属性​​Element.clientWidth​​:元素可视宽度。​​Element.clientHeight​​:元素可视高度。​​MouseEvent.clientX​​:鼠标相对于浏览器左上顶点的水平坐标。​​MouseEvent.clientY​​:鼠标相对于浏览器左上顶点的垂直坐标。​​Touch.clientX​​:触点相对于浏览器左上顶点的水平坐标(移动端属性)。​​T

首先要学习什么:docker 还是 kubernetes?_crmeb中邦科技的博客-多极客编程

Docker 和 Kubernetes 是完全不同的技术。学习他们两个都非常重要。那么,两者有什么区别呢?谈到应用​​程序开发​​,很多人想知道该选择什么,Docker 或 Kubernetes。但是,这两种技术对于适当的容器化都至关重要。因此,同时学习它们可以使您在竞争中领先,并使您成为需要的专业人士。当我们谈到 容器技术时,​​Docker​​ 和 ​​Kubernetes​​ 都是开源的领导

jwt 实现登录认证 + token 自动续期方案_crmeb中邦科技的博客-多极客编程

JWT 实现登录认证 + Token 自动续期方案,这才是正确的使用姿势!项目中基本都有用户管理模块,而用户管理模块会涉及到加密及认证流程。今天就来讲讲认证功能的技术选型及实现。技术上没啥难度当然也没啥挑战,但是对一个原先没写过认证功能的人来说也是一种锻炼吧技术选型要实现认证功能,很容易就会想到 JWT 或者 session,但是两者有啥区别?各自的优缺点?应该 Pick 谁?夺命三连区别基于 s

中文乱码的几种解决方法_crmeb中邦科技的博客-多极客编程

首先说明我的特殊情况:在前台jsp中,我使用了form post请求,设置enc,页面编码格式为utf-8。后台我用的是commons-fileUpload组件,ServletFileUpload解析表单表单和文件。设置 request.setCharacterEncoding("UTF-8");设置了ServletFileUpload .setHeaderEncoding("UTF-8")在To

在vue3这样子写页面更快更高效-多极客编程

前言在开发管理的后台过程中,会增加、删除、更改很多页面,这些页面的逻辑大多相同,比如获取列表数据、分页、筛选等基本功能。不同的是呈现的数据项。还有一些操作按钮。对于刚开始只有 1,2 个页面的时候大多数开发者可能会直接将之前的页面代码再拷贝多一份出来,而随着项目的推进类似页面数量可能会越来越多,这直接导致项目代码耦合度越来越高。这也是为什么在项目中一些可复用的函数或组件要抽离出来的主要原因之一下面

前端三个实用小妙招分享给大家-多极客编程

前言整理下本人在工作中撸代码遇到的一些刚看时一脸懵,实则很简单就能解决的小妙招,希望对大家有所帮助~伪元素动态改变其样式我们都用过伪元素,什么::before,::after啊这些等等,但是他们都不会直接在代码里html中生成标签,那么有时我们不行再加dom元素了,明明就用改dom元素的伪元素更简单,如下图:那个蓝色的进度条就是用动态改变伪元素样式的方式来实现的,那么接下来来看下具体实现方案吧!在