效果预览
代码链接
提交历史
API设计 需求
用户怎么用该组件 1 2 3 4 5 6 7 8 9 10 11 <x-button @click =? @focus =? @mouseover =? theme ="default or primary or link" level ="nomal or info or warning or success or danger" size ="mini or small or normal or large" disabled loading > </x-button >
Vue3笔记 属性绑定 非Prop 属性继承 参考文档
如果父组件传给子组件的属性,子组件中没有相应 props或 emits定义,则这些属性被称为非Prop属性
当组件返回单个根节点 时,Vue3会默认将所有非 prop属性绑定到子组件的根元素。
基于此特性,父组件中绑定的事件可以直接传至子组件,因此可以初步实现button组件对事件的支持,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <template> <x-button @click="clickButton" @focus="clickButton" @mouseover="clickButton" > 点我 </x-button> </template> <script lang="ts" > import XButton from "../lib/Button.vue" ;export default { components: { Button }, setup ( ) { const clickButton = ()=> { console .log(1 ) } return {clickButton} } }; </script>
1 2 3 4 5 6 7 8 <template > <div class ="x-button-dv" > <button class ="x-button" > <slot > </slot > </button > </div > </template >
禁用属性继承 从上面的代码中,不难发现一个问题——button组件的事件其实应该绑定给<button/>元素而不是其根元素;而事件之外的其他属性需绑定给根元素。解决这些问题的思路如下:
通过将 inheritAttrs 选项设置为 false,禁用非prop属性的继承
获取传来的属性,通过v-bind将事件绑定给<button/>元素
将其余属性绑定给根元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template> <div class ="x-button-dv" :size="size" > <button class ="x-button" v-bind="rest" > <slot></slot> </button> </div> </template> <script> export default { name: 'x-button' , inheritAttrs: false , setup (props, context) { const { size, ...rest } = context.attrs return { size, rest } } } </script>
props V.S. attrs
props要先声明才能取值,attrs不用声明
当props声明了属性时,该属性不能在attrs里面取到
props不包含事件,attrs包含
当属性的数据类型为Booalen时,必须要给该属性绑定value,否则attrs中为空字符串
1 2 3 4 5 6 7 8 9 // 父组件 <x-button size ="small" disabled :multiple ="true" @click ="clickButton" @mouseenter ="clickButton" @focus ="clickButton" > 点我 </x-button >
1 2 3 4 5 6 7 8 9 10 11 12 props: { size: { type: String } }, setup (props, context) { console .log( {...props}) console .log( {...context.attrs}) const { size, ...rest } = context.attrs return { size, rest } }
补充 css影响最小原则 CSS 绝对不能影响库使用者
尽量不使用 scoped 因为 data-v-xxx 中的 xxx 每次运行可能不同 必须输出稳定不变的 class 选择器,方便使用者覆盖
必须加前缀,不容易被使用者覆盖
css写loading动画 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .xx-loadingIndicator { $main-theme-color : #87dfd6 ; width : 14px ; height : 14px ; display : inline-block; margin-right : 4px ; border-radius : 14px ; border-color : $main-theme-color $main-theme-color $main-theme-color transparent; border-style : solid; border-width : 2px ; animation : xx-spin 1s infinite linear; } @keyframes xx-spin { 0% { transform : rotate(0deg ) } 100% { transform: rotate(360deg ) } }
总结
Vue 属性继承
默认属性传给根元素
inheritAttrs: false 禁用属性继承
v-bind="$attrs"绑定属性, context.attrs获取属性
props V.S. attrs