11.样式
2024/10/7大约 4 分钟
11.样式
- 样式与
html5中写法并无区别,样式语法相关内容见css笔记
11.1 获取响应式属性
使用
v-bind(var)可以在style块中获取对应的响应式属性值,包括响应式对象中的属性v-bind()中相当于在style中使用js语法(如果不是单个变量需要使用引号包裹起来),最终编译后会得到一个跟随使用值变化的css变量- 使用变量名:可以直接使用一个变量名
name作为的参数,获取对应的变量值 - 使用直接的字符串拼接:仅限于
css格式,可以使用直接的字符串拼接作为参数,获取到的结果也将拼接上字符串 - 使用变量属性:也可以使用
'obj.property'作为参数,获取对应的变量obj的属性property - 使用行内
js表达式:甚至可以使用一个js表达式字符串作为参数,可以使用字符串拼接和三目运算符
/* const base = ref(400); */ .base { /* 直接使用变量名作为参数 */ /* 变量名称为 --f12d55ef-base */ font-weight: v-bind(base); /* 使用直接的字符串拼接作为参数 */ /* 变量名称为 --f12d55ef-base\+\"rem\" */ font-size: v-bind(base+"rem"); /* 使用变量属性作为参数 */ /* 变量名称为 --f12d55ef-obj\.size */ font-size: v-bind('obj.size'); /* 使用行内js表达式作为参数 */ /* 变量名称为 --f12d55ef-base\+\"1rem\" */ font-size: v-bind('base + "1rem"'); }可以发现除了第一种情况,其他情况的样式变量名会暴露计算细节,如果绑定来源是用户输入可能有注入隐患
- 使用变量名:可以直接使用一个变量名
实现原理是在对组件最外层标签
style上添加css变量值,变量名称开头有唯一的组件id避免混淆,在使用v-bind()的地方用var(对应变量)代替,对less和scss格式有以下需要注意- 在
less和scss中第二种直接的字符串拼接方法的解析可能出现问题,比如数字变量添加单位的情况,相关研究可结合此博客 - 如果是预编译条件
@if或@each等中使用的变量,因为这个编译是在运行前完成的,动态控制无效
.base { font-weight: v-bind(base); } // 对于 scss 中变量加单位 // 最终得到 css 变量名为 --f12d55ef-base\ \+\ \'rem\' // 但希望使用的 css 变量为 --f12d55ef-baserem // 对应不上 font-size:v-bind(base + 'rem'); // 这样可以对应上 font-size:v-bind('base + "rem"'); // 考虑使用 calc 进行计算,而不是简单的拼接 $base:v-bind(base); font-size:calc($base * 1rem); .pre-compile { // 编译已经固定,不会根据值变化而切换 @if $base > 400 { font-size: 12px; } @else { font-size: 16px; } }- 在
11.2 使用scss
- 安装
sass和解析器
# 老仓库
# npm install sass sass-loader
# 新仓库,dart重写,性能更好
npm install sass-embedded -D- 在需要使用的单文件
style块上添加lang=scss字段 - 创建全局文件存储项目共用的
scss变量 - 在vit.config.ts中添加全局引入文件,也可在入口文件或单文件
style块中import
export default defineConfig({
css:{
preprocessorOptions:{
scss:{
additionalData:'@import "@/assets/style/mixin.scss";'
}
}
},
})11.3 样式穿透
由于
vue中一般使用scoped关键字将组件的css的作用域缩小到单文件中,隔离样式,但有时父组件需要修改子组件的样式就变得困难,因此设计了样式穿透,样式穿透实际上仅为:deep语法,实验下来也可以考虑其他的穿透方法如果需要在父组件中直接影响子组件样式需要使用
:deep()// 之前还曾使用过 >>> 或 /deep/ 关键字(已弃用)进行样式穿透 // Deprecation(lang=css): .father /deep/ .son // 父组件 .father:deep(.son) { color: red; } // 子组件 .son { color: greed; }在子组件标签上定义
class,这样定义的class会出现在子元素类的末尾,优先级最高,在其中直接覆写的样式会生效,但限制也不少- 父组件虽然可以在子组件标签上添加
class属性,但如果子组件中不止一个根元素,那么class定义的样式将不会被添加 - 虽然直接添加可以生效,但子组件可能存在嵌套元素和样式,这时靠从最外层标签直接继承样式明显困难
标签上定义的class会出现在末尾 - 父组件虽然可以在子组件标签上添加
子组件对需要修改样式的标签添加可传
style值的方法,支持父组件定义样式对象并传给子组件使用<script setup lang="ts"> const styleObj = reactive({ color: 'red' }) </script> <template> <son :style="styleObj" /> <!-- 内部接收并赋值 --> <div :style="styleObj">Hello</div> </template>
