props自定义限制
props: {size: {// 自定义验证函数validator: (val) => {return ["small", "medium", "large"].includes(val);},}
}
这个验证函数接受一个实际传入的 prop
值,验证并返回 true
或 false
下面将要说的是透传属性和插槽,此技巧在二次封装别人组件的时候非常有用
透传属性
$attrs
包含所有透传过来的对象,除显式声明接受的props
、emits
、slots
useAttrs()
const attrs = useAttrs();
const filteredAttrs = computed(() => {return { ...attrs, style: undefined };
});
$attrs
还可与$listeners
搭配使用,$listeners
包含了父组件传递的事件(不包含.native
修饰器),它可以通过v-on="$listeners"
转发传入内部组件,进行对事件的监听处理
注意: $listeners
组件实例属性在Vue3.x
被取消,其监听都整合到了$attrs
属性上
单个slot透传
多个slot透传
多个slot透传作用域插槽
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')
}
$slots
对象,包含所有的插槽对象,结构如下:const $slots = {
"default": [{...}],
"slotA": [{...}],
"slotB": [{...}]
}
我们可以使用v-if
有条件的渲染slot
更加合理,并且我们封装通用组件的时候最好预留个slot
更好扩展
window.addEventListener('mousedown', e => {// 获取被点击的元素const clickedEl = e.target;// `targetEl` 为检测的元素if (targetEl.contains(clickedEl)) {// 在"targetEl"内部点击} else {// 在"targetEl"之外点击}
});
动态组件:tab切换的时候可使用动态组件动态加载并缓存提供动效
递归组件:模板里面自己自己,注意需要设置条件退出,不然会无限渲染,适合嵌套菜单,树形控件等
{{ tree.label }}
DOM
更新循环结束之后执行延迟回调DOM
mounted(){this.$nextTick(() => {this.$refs.inputs.focus(); //通过 $refs 获取dom 并绑定 focus 方法})
}
直接最佳写法如下:
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);
这种形式看起来太麻烦了,我们甚至可以将其属性和方法挂载到window
对象上,这样全局直接也可以访问
v-if
方法来控制 router-view
的显示隐藏
需要的页面可注入该方法使用
或者直接使用v-if
操作该组件
或者借助Vue
的diff
算法,我们给元素设置一个唯一的key
值然后去改变它
Vue组件的API主要包含三部分:props
、event
、slot
props
为组件接收的参数,最好用对象的写法,可更好设置类型默认值和自定义校验event
用于子组件向父组件传递消息slot
可以给组件动态插入一些内容或组件,是实现高阶组件的重要途径组件封装最好还应遵循单向数据流,传递的props
仅仅做展示,如需修改,则应该重新初始化一份全新的响应式数据并将props
深拷贝后作为初始值
为 Vue
中的错误和警告提供自定义处理程序
// Vue 3
const app = createApp(App);
app.config.errorHandler = (err) => {console.error(err);
};
// Vue 2
Vue.config.errorHandler = (err) => {console.error(err);
};
template
标签可以在模板内的任何地方使用,不参与实际标签渲染,可减少嵌套层级,简化代码逻辑
{{ title }}
{{ description }}
上面代码v-if
逻辑分组后:
{{ title }}
{{ description }}
在模板中使用 v-for
遍历输出数据,可以使用解构语法
{{ user }}
有时候我们想跳出scoped
这个限定作用域,更改子组件的样式但不会影响全局样式,我们就可以使用深度选择器来完成
上面代码会被解析为
[data-v-e44d851a] .ant-card-head-title {background: green;
}
注意:vue
版本和预处理器不同,深度选择器的写法也会不同,灵活使用即可
当我们当前组件使用到了Card
组件
其中的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},
};
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享