define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Base
{
public:
static void func()
{
cout << "父类中静态func调用" << endl;
}
static void func(int a)
{
cout << "父类中静态func(int a)调用" << endl;
}
static int m_A; // 静态成员变量 // 类内声明
};
int Base::m_A = 10; // 类外赋值
class Son :public Base
{
public:
static void func()
{
cout << "子类中静态func调用" << endl;
}
static int m_A; // 静态成员变量 // 类内声明
};
int Son::m_A = 100; // 类外赋值
------------------------------------------------------------------
void test01()
{
Son s1;
// 通过对象访问静态成员变量
cout << s1.m_A << endl; // 结果: 100
cout << s1.Base::m_A << endl; // 结果: 10
//通过类名访问静态成员变量
cout << Son::m_A << endl;
cout << Son::Base::m_A << endl;
}
------------------------------------------------------------------
void test02()
{
Son s2;
// 通过对象访问静态成员函数
s2.func(); // 结果:子类中静态func调用
s2.Base::func(); // 结果:父类中静态func调用
s2.Base::func(1); // 结果:父类中静态func(int a)调用
// 通过类名访问静态成员函数
Son::func();
Son::Base::func();
Son::Base::func(1);
}
// 注意 Son::Base::func(); 第一个::是通过类名访问 第二个::是作用域 注意区别
本篇文章主要讲述Unocss的使用和个人使用之后的感想
在此之前还写过一篇关于反对在Vue里使用tailwind CSS的一篇文章(主写Vue的,React等框架中没有抵抗)。当然,当时写那篇文章的时候脑子也有是有点迷糊的,后来被怼的的很惨,不敢吭声。
近一段时间,公司里给安排了一个新项目,这次我选择安排上了Unocss+sass来写样式。但为什么本身就比较反对在Vue中使用原子化CSS的我,却在新的项目中使用了Unocss呢?
理由很简单:主要还是原子化CSS最近被炒的非常热,前端技术本来更新的就快,并不是说讨厌某一个技术就要极力去抵抗的(当然也不是说讨厌,只是觉得Vue的css处理已经非常棒了,在Vue中可能不会那么需要一个额外的css框架来支持),还是有就是当时说tailwind CSS不适合用在Vue中使用的时候,有部分人说我没写过tailwind CSS。哎,我就不写tailwind CSS我写Unocss (。・ω・。)
下载安装Unocss
npm i unocss
或
yarn add unocss
安装之后为了更好的IDE使用体验,官方是比较建议创建一个单独的文件来配置Unocss
在项目的根目录下创建uno.confin.{js,ts,mjs,mts}文件
//uno.config.ts
import { defineConfig } from "unocss";
export default defineConfig({
//...Unocss的配置项 看下面配置介绍
});
还需要在vite.config.ts中引入一下
//vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import UnoCss from "unocss/vite";
export default defineConfig(({ command }) => ({
plugins: [
vue(),
//插件中也可以选择指定uno文件地址 参数{configFile: './uno.config.ts'}
//当然默认不传参数也是可以正常运行的 这里就不选择传入参数了
UnoCss()
],
//....
})
//另外webpack5中 webpack.config.js
const UnoCSS = require('@unocss/webpack').default
module.exports = {
plugins: [UnoCSS()],
optimization: { realContentHash: true }
}
这样在uno.config.ts文件中配置好后,就可以写现在火热的原子化样式了
<div class="h-full text-center flex select-none all:transition-400">
<p text-16 px-10 shadow="[0_0_10px_4px_#dedede]">iceCode</p>
</div>
Unocss的配置还是挺多的,但是一般情况下很少全部用到,仅有几个配置就可以覆盖大多数的场景
这个配置主要制定自己样式的规则,这个个人觉得可能会有一部分
rules: [
//静态规则 生成 .m-1 { margin: 0.25rem; }的样式
['m-1', { margin: '0.25rem' }],
//动态规则 使用正则表达式进行匹配 可以动态的进行匹配
//m-3 转化成css .m-3 { margin: 0.75rem; } m-100 转化成css .m-100 { margin: 25rem; }
[/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
//如果有需要 还可以更高级 当然大多数情况下用不到
[
/^custom-(.+)$/,
([, name], { rawSelector, currentSelector, variantHandlers, theme }) => {
// 丢弃不匹配的规则
if (name.includes('something')) return
// 如果你想的话,可以禁用这个规则的变体
if (variantHandlers.length) return
const selector = e(rawSelector)
// 返回一个字符串而不是对象
return `
${selector} {
font-size: ${theme.fontSize.sm};
}
/* 你可以有多条规则 */
${selector}::after {
content: 'after';
}
.foo > ${selector} {
color: red;
}
/* 或媒体查询 */
@media (min-width: ${theme.breakpoints.sm}) {
${selector} {
font-size: ${theme.fontSize.sm};
}
}
`
}
]
]
可以自己设置一些自己的特定场景来指定自己的预设,当然也可以使用Unocss社区提供的预设来进行配置
创建要给自己的预设
// my-preset.ts
import { Preset } from 'unocss'
export default function myPreset(options: MyPresetOptions): Preset {
return {
name: 'my-preset',
rules: [
// ...
],
variants: [
// ...
]
// 它支持您在根配置中拥有的大多数配置
}
}
在使用的的时候引入到 presets 中去即可
// unocss.config.ts
import { defineConfig } from 'unocss'
import myPreset from './my-preset'
export default defineConfig({
presets: [
myPreset({
/* 预设选项 */
})
]
})
主要还是看个人需求,预设这个东西还是用别人制定好的最香。
该预设继承preset-wind和preset-mini两个预设
该预设尝试提供流行的功能优先框架(包括 Tailwind CSS、Windi CSS、Bootstrap、Tachyons 等)的共同超集。所以怎么写规则怎么使用可以完全按照这些官网上的写
// uno.config.ts
import { defineConfig,presetUno } from 'unocss'
export default defineConfig({
presets: [presetUno()]
})
例如,ml-3(Tailwind)、ms-2(Bootstrap)、ma4(Tachyons)和 mt-10px(Windi CSS)都是有效的。
.ma4 {
margin: 1rem;
}
.ml-3 {
margin-left: 0.75rem;
}
.ms-2 {
margin-inline-start: 0.5rem;
}
.mt-10px {
margin-top: 10px;
}
使用属性化预设可以更好的简化模板中css样的代码
// uno.config.ts
import { defineConfig,presetUno,presetAttributify } from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetAttributify()
// ...
]
})
当使用tailwind CSS写一个工具类的按钮时,过长的样式就会使项目难以维护
<button
class="bg-blue-400 hover:bg-blue-500 text-sm text-white
font-mono font-light py-2 px-4 rounded border-2
border-blue-200 dark:bg-blue-500 dark:hover:bg-blue-600"
>
Button
</button>
可以这时属性化预设就可以很大程度上的简化这些写作的样式
//这样写 是否清晰很多
<button
bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
text="sm white"
font="mono light"
p="y-2 x-4"
border="2 rounded blue-200"
>
Button
</button>
当然也有一般情况下并不会写这么多样式在模板上
<button class="border border-red">Button</button>
//还可以这样使用
<button border="~ red">Button</button>
//也可以抛弃class
<div m-2 rounded text-teal-400 />
可以使用纯css图标,首先还需要下载icon
npm install -D @iconify/json 也可以只下载 某一个你要使用的图标 npm install -D @iconify-json/[the-collection-you-want]
//或者
yarn add @iconify/json 也可以只下载 某一个你要使用的图标 yarn add @iconify-json/[the-collection-you-want]
// uno.config.ts
import { defineConfig,presetIcons } from 'unocss'
export default defineConfig({
presets: [
presetIcons({
/* options */
})
// ...other presets
]
})
使用时只需要写class即可
<!-- Phosphor 图标中的基本锚点图标 -->
<div class="i-ph-anchor-simple-thin" />
<!-- 来自 Material Design 图标的橙色闹钟 -->
<div class="i-mdi-alarm text-orange-400" />
可以通过配置的provider属性来使用字体
目前仅支持:
// uno.config.ts
import { defineConfig,presetWebFonts,presetUno } from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetWebFonts({
provider:'none',
/* options */
})
]
})
UnoCSS 的 TailWind/Windi CSS 预设。继承于preset-mini。
UnoCSS 的基本预设,仅包含最基本的实用工具。
可以将css样式作为HTML的标签使用,当使用单个样式的时候会比较好用。
// uno.config.ts
import { defineConfig,presetTagify } from 'unocss'
export default defineConfig({
presets: [
presetTagify({
/* options */
})
// ...other presets
]
})
配置标签预设之后,单个样式可以作为标签使用了
<text-red>red text</text-red>
<flex>flexbox</flex>
<!--可以理解为-->
<span class="text-red">red text</span>
<div class="flex">flexbox</div>
众所周知,这个css框架使用的都是rem作为单位,如果想要在Unocss中使用px需要写上固定的px单位,这样显得不够简洁,这里就可以使用这个预设自动转将rem转化为px
这个预设不包含在unocss包中,需要单独的额外下载
npm install -D @unocss/preset-rem-to-px
//或
yarn add -D @unocss/preset-rem-to-px
// uno.config.ts
import { defineConfig } from 'unocss'
import presetRemToPx from '@unocss/preset-rem-to-px'
export default defineConfig({
presets: [
presetRemToPx({
baseFontSize: 4, //基准字体大小 官方的默认预设16(1单位 = 0.25rem)所以这里为4 为1:1
})
// ...other presets
]
})
这里在使用样式的时候,直接写数字就是px为单位的样式
<div class="m-2"></div>
//css
.m-2 {
margin: 2px;
}
Transformers 用于转换源代码以支持约定。
它提供了一个统一的接口来转换源代码以支持约定。
// my-transformer.ts
import { createFilter } from '@rollup/pluginutils'
import { SourceCodeTransformer } from 'unocss'
export default function myTransformers(
options: MyOptions = {}
): SourceCodeTransformer {
return {
name: 'my-transformer',
enforce: 'pre', // 在其他transformer之前执行
idFilter() {
// 只转换 .tsx 和 .jsx 文件
return id.match(/\.[tj]sx$/)
},
async transform(code, id, { uno }) {
// code 是一个 MagicString 实例
code.appendRight(0, '/* my transformer */')
}
}
}
当然,他也有着自己的几个转换器
为 UnoCSS 启用 Windi CSS 的 变体组特性。
// uno.config.ts
import { defineConfig,transformerVariantGroup } from 'unocss'
export default defineConfig({
// ...
transformers: [
transformerVariantGroup(),
],
})
启用这个预设的时候,就可以将一些前缀相同的属性以组的形式来写
<div class="hover:(bg-gray-400 font-medium) font-(light mono)"/>
//转化为
<div class="hover:bg-gray-400 hover:font-medium font-light font-mono"/>
//个人感觉这种不如上面的 属性化预设 使用属性化预设可以写成 看个人喜好
<div hover='bg-gray-400 font-medium' font='light mono'/>
启用指令转换器将支持 @apply、@screen 和 theme() 指令。
// uno.config.ts
import { defineConfig,transformerDirectives } from 'unocss'
export default defineConfig({
// ...
transformers: [
transformerDirectives(),
],
})
.custom-div {
@apply text-center my-0 font-medium;
}
//转化为
.custom-div {
margin-top: 0rem;
margin-bottom: 0rem;
text-align: center;
font-weight: 500;
}
.grid {
--uno: grid grid-cols-2;
}
@screen xs {
.grid {
--uno: grid-cols-1;
}
}
@screen sm {
.grid {
--uno: grid-cols-3;
}
}
//转换为
.grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 320px) {
.grid {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
}
@media (min-width: 640px) {
.grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.btn-blue {
background-color: theme('colors.blue.500');
}
//转化为
.btn-blue {
background-color: #3b82f6;
}
这个转换器可以将写在一个元素上的样式编译成一个类名
// uno.config.ts
import { defineConfig,transformerCompileClass } from 'unocss'
export default defineConfig({
// ...
transformers: [
transformerCompileClass(),
],
})
在类字符串的开头加上:uno:即可将后面所写的样式编译成一个类名,不支持属性化预设
<div class=":uno: text-center sm:text-left">
<div class=":uno: text-sm font-bold hover:text-red"/>
</div>
<!--将编译成 -->
<div class="uno-qlmcrp">
<div class="uno-0qw2gr"/>
</div>
//css
.uno-qlmcrp {
text-align: center;
}
.uno-0qw2gr {
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 700;
}
.uno-0qw2gr:hover {
--un-text-opacity: 1;
color: rgba(248, 113, 113, var(--un-text-opacity));
}
@media (min-width: 640px) {
.uno-qlmcrp {
text-align: left;
}
}
这个转换器主要作用于 在jsx文件内写 属性化预设的样式
// uno.config.ts
import { defineConfig, presetAttributify,transformerAttributifyJsx } from 'unocss'
export default defineConfig({
// ...
presets: [
// ...
presetAttributify()//属性化预设
],
transformers: [
transformerAttributifyJsx(), // <--
],
})
如果没有这个转换器,在jsx中使用属性化预设将会将无值的样式识别成布尔值
export function Component() {
return (<div text-red text-center text-5xl animate-bounce>
unocss
</div>)
}
//这里将会转换为
export function Component() {
return (
<div text-red="" text-center="" text-5xl="" animate-bounce="">
unocss
</div>
)
}
个人感觉剩下的配置一般情况下都不太能使用的到,也看项目环境吧。
可以在属性内配置一些原子化样式的快捷方式,并且可以类似于Rules一样配置动态快捷方式。
shortcuts: {
// 使用原子化样式定义快捷类
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-green': 'text-white bg-green-500 hover:bg-green-700',
//使用动态创建快捷方式
[/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`]
}
UnoCSS 也支持像 Tailwind / Windi 中的主题系统。在用户级别上,您可以在配置中指定 theme 属性,它将与默认主题进行深度合并。
theme: {
// ...
colors: {
'veryCool': '#0000ff', // class="text-very-cool"
'brand': {
'primary': 'hsla(var(--hue, 217), 78%, 51%)', //class="bg-brand-primary"
}
},
}
//在rules中使用
rules: [
[
/^text-(.*)$/,
([, c], { theme }) => {
if (theme.colors[c]) return { color: theme.colors[c] }
}
]
]
允许对现有规则应用一些变化,例如hover:变体
variants: [
// hover:
(matcher) => {
if (!matcher.startsWith('hover:'))
return matcher
return {
// 去掉前缀并将其传递给下一个变体和规则
matcher: matcher.slice(6),
selector: s => `${s}:hover`,
}
}
],
rules: [
[/^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
]
内部实现
提取器用于从源代码中提取工具的使用情况。
默认情况下,会使用 extractorSplit 进行拆分。该提取器会将源代码拆分为标记,然后直接提供给引擎。
从配置中注入原始 css 作为预处理。解析的 theme 可用于自定义 css。
preflights: [
{
getCSS: ({ theme }) => `
* {
color: ${theme.colors.gray?.[700] ?? '#333'};
padding: 0;
margin: 0;
}
`
}
]
主要用于css的顺序的优先级问题,css的顺序影响他们的优先级,这了可以在自定义样式时,添加图层来固定css顺序
rules: [
[/^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` }), { layer: 'utilities' }],//添加图层
// 当您省略图层时,它将是 `default`
['btn', { padding: '4px' }]
]
//也可以在与检查中调用预设样式,进行图层设置
preflights: [
{
layer: 'my-layer',
getCSS: async () => (await fetch('my-style.css')).text()
}
]
图层自定义
ts
在智能建议在演示平台和VS Code 扩展中可以进行定制。针对于智能提示的属性
autocomplete: {
templates: [
// 主题推断
'bg-$color/<opacity>',
// 简写
'text-<font-size>',
// 逻辑或组合
'(b|border)-(solid|dashed|dotted|double|hidden|none)',
// 常量
'w-half',
],
shorthands: {
// 等同于 `opacity: "(0|10|20|30|40|50|60|70|90|100)"`
'opacity': Array.from({ length: 11 }, (_, i) => i * 10),
'font-size': '(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)',
// 覆盖内置的简写
'num': '(0|1|2|3|4|5|6|7|8|9)'
},
extractors: [
// ...extractors
]
}
import {
defineConfig,
presetUno,
presetAttributify,
presetTypography,
presetIcons,
transformerVariantGroup,
transformerAttributifyJsx,
transformerCompileClass,
transformerDirectives,
} from "unocss";
import presetRemToPx from "@unocss/preset-rem-to-px";
export default defineConfig({
//自定义规则
rules: [[/^bg-?([0123456789abcdef]+)$/i, ([_, rgb]) => ({ background: `#${rgb}` })]],
//预设规则 有前两个预设可以满足95%以上的需求
presets: [
//此预设规则可以看Tailwind CSS、Windi CSS、Bootstrap、Tachyons官网了解相关规则
presetUno(), //m-10 理解为 margin:10rem 或者 m-10px 理解为 margin:10px
presetAttributify(), //归因模式 bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600" 背景颜色的简写 也可以再元素上不加class 直接写属样式 例如 <div m-2 p-10 bg-000></div>
// presetTypography(), //排版预设 详细排版看https://unocss.dev/presets/typography#colors 使用这个前两个必须
// presetIcons(), //css图标 支持图标看 https://icones.js.org/ 需要下载
// 这里看个人需求是否要使用px
presetRemToPx({
baseFontSize: 4, //基准字体大小 官方的默认预设(1单位 = 0.25rem) html的字体是16 所以这里为4
}), //默认unocss默认是rem 转换成 px单位
],
//看个人需求添加转换器
transformers: [
transformerVariantGroup(),
transformerAttributifyJsx(),
transformerCompileClass(),
transformerDirectives()
],
//以下可以按个人需求添加
shortcuts:{},
layers: {},
theme: {},
variants: [],
extractors: [],
preflights:[]
});
问题主要针对 属性化预设的问题,由于 属性化预设的简洁、书写方便,大多数场景下可使用属性化来写样式,但是属性化存在着一些问题
<div w100% shadow-[0_0_10px_#dedede] bg-#333></div>
以上这些写法都是会报错的,属性中不允许包含%\[]\#等一些特殊符号的,所以包含颜色或者自定义等含有特殊符号无使用属性化来写样式
属性化支持有值多属性写法,可以使用这种形式来写属性化样式,当然中写的还不如直接一个class的好
<div w="100%" shadow="[0_0_10px_#dedede]" bg="#333"></div>
不过当一些有着多属性时,这种写法较为舒服
<div border="1px solid #dedede" h="[calc(100vh-500px)]" text="16 #000 center"></div>
<!--对比tailwind CSS -->
<div class="border-1 border-solid border-[#dedede] h-[calc(100vh-500px)] text-16 text-[#000] text-center"></div>
另外class和属性化的负数值写法是不同
<!--这里mb--20 可以理解为 margin-bootom:-20px-->
<p text="24 center #222 hover:color-red-400" fw-800 mb--20>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Explicabo veniam aut esse iure mollitia. Earum omnis aliquid minus porro nulla commodi dignissimos, voluptatem
accusamus cumque reprehenderit, ea nisi perferendis quis.
</p>
<!--如果使用 class 来写负值-->
<!--这里写负值写在前面即可 -mb-20 理解为 margin-bootom:-20px-->
<p class="text-24 text-center text-#222 fw-800 hover:text-red-400 -mb-20">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Explicabo veniam aut esse iure mollitia. Earum omnis aliquid minus porro nulla commodi dignissimos, voluptatem
accusamus cumque reprehenderit, ea nisi perferendis quis.
</p>
创建单独的uno.config.ts文件就是为了在IDE中配合插件使用,在一个页面中如果这样写可能会看着很乱,当配合插件之后,会比较清晰明了一些
在应用商店直接搜Unocss
安装完成之后,你页面中所写的样式都会给标明出来
另外在安装最新的插件之后,有可能会产生没有样式标识和样式提示的问题,这里需要在settings.json(这里是针对vscode的问题) 文件中添加一个属性
//settings.json
{
//其他配置
//...
//假如你的项目在D:/git-item/my-item/你所保存的所有项目,那么这里的属性值就可以是D:/git-item/my-item(或者加上你的详细项目)
"unocss.root": "你当前项目的绝对路径",
}
原子化样式目前来说是一种CSS的发展趋势,可以使用。也可以选择不用,毕竟现在的CSS已经发展很成熟了,包括Sass、Less等一些预编译器也发展的很成熟,他们都有自己变量函数等一些操作,如果想要写一个主题,使用变量来实现是一个很好选择。
当然,最后个人觉得原子化样式在Vue、Servlet等这种对CSS的处理很好的框架中不是很好的选择。如果是React等这种对CSS处理没有那么好的框架中,除了CSS-in-JS还是很不错的选择
原文链接:https://juejin.cn/post/7322401091237068854
动态的 web 应用同样需要静态文件。CSS 和 JavaScript 文件通常来源于此。理想情况下,你的 web 服务器已经配置好为它们服务,然而在开发过程中 Flask 就能够做到。只要在你的包中或模块旁边创建一个名为static 的文件夹,在应用中使用 /static 即可访问。
给静态文件生成 URL ,使用特殊的 static 端点名:
url_for('static', filename='style.css')
这个文件是应该存储在文件系统上的static/style.css。
在 Python 中生成 HTML 并不好玩,实际上是相当繁琐的,因为你必须自行做好 HTML 转义以保持应用程序的安全。由于这个原因,Flask 自动为你配置好 Jinja2 模板。
你可以使用方法 render_template() 来渲染模板。所有你需要做的就是提供模板的名称以及你想要作为关键字参数传入模板的变量。
这里有个渲染模板的简单例子,在 /home/mysite/Code 目录下新建 hello.py 文件,并向其中添加如下代码:
Flask 将会在 templates 文件夹中寻找模板。因此如果你的应用是个模块,这个文件夹在模块的旁边,如果它是一个包,那么这个文件夹在你的包里面:
比如,应用是模块:
比如,应用是包:
/application /__init__.py /templates /hello.html
对于模板,你可以使用 Jinja2 模板的全部能力。详细信息查看官方的 Jinja2 Template Documentation 。
在 /home/mysite/Code 目录下新建 templates 文件夹并在其中新建 hello.html 文件:
照前面的方法运行应用程序,当访问 http://127.0.0.1:5000/hello/ 时页面显示 Hello World!;当访问 http://127.0.0.1:5000/hello/shiyanlou 时页面显示 Hello shiyanlou!。
在模板中你也可以使用request,session和g对象,也能使用函数get_flashed_messages() 。
模板继承是十分有用的。如果想要知道模板继承如何工作的话,请阅读文档模板继承。基本的模板继承使得某些特定元素(如标题、导航和页脚)在每一页成为可能。
自动转义默认是开启的,因此如name包含 HTML,它将会自动转义。如果你信任一个变量,并且你知道它是安全的(例如一个模块把 wiki 标记转换到 HTML ),你可以用Markup类或|safe过滤器在模板中标记它是安全的。 在 Jinja 2 文档中,你会见到更多例子。
下面有一个Markup类如何工作的基本介绍,在 Python3 交互式命令行中执行如下命令:
*请认真填写需求信息,我们会在24小时内与您取得联系。