前言

CSS 代码多了就不好管理了, 这是它语法先天的不足.

Sass 就是加强它语法的, Sass 为 CSS 引入了一些 JS 语言的特性, 比如 variable, function, parameter, extend, import.

Sass 的 variable 和 import (用于管理), 和 CSS 的 variable, import 不是一回事儿. 分开看待会更好理解.

它的原理很简单, 就是解析 Sass 语法, 然后编辑去 CSS. 和 TS > JS 一样的道理.

参考:

Learn Sass In 20 Minutes | Sass Crash Course

官方网站

How to Compile?

搭配 Webpack 的话, 看这篇 : Webpack 学习笔记

这里使用的方式是 VS Code Extension.

安装插件

注: 它有 2 个同名字的哦, 旧的没有维护了 github issue, 旧的 version 使用 @use 会报错哦.

点击 Watch Sass 开启 watching mode.

这时, scss 文件就会被 compile 生成 css 文件了 (.map 是 debug 用的)

Output window 一直弹出来的问题, 它默认是 information 所以一直会跳出来.

如果不用 webpack 又不用 extension 也可以用 nodejs 单独版本, 看这篇: Youtube – Stop using an extension to compile Sass

补上一个 Gulp 版本

npm install --global gulp-cli
yarn add sass --dev
yarn add gulp --dev
yarn add gulp-sass --dev
yarn add gulp-sourcemaps --dev

gulpfile.js

const { src, dest, watch } = require("gulp");
const sass = require("gulp-sass")(require("sass"));
const sourcemaps = require("gulp-sourcemaps"); function sassTask() {
return src("./src/**/*.scss")
.pipe(sourcemaps.init())
.pipe(sass().on("error", sass.logError))
.pipe(sourcemaps.write("."))
.pipe(dest("src/"));
} exports.build = sassTask;
exports.watch = function () {
watch("./src/**/*.scss", sassTask);
};

folder and files 结构

只要是 src 里面的 .scss 都会被 transplie 成 .css, 位置是 sibling

运行 command

yarn run gulp watch
or
yarn run gulp build

注意: for 第一次, 最好先 gulp build 一次创建出所有的 files. gulp watch 只有在 file change 的时候才会执行的哦.

Variable

CSS 的 variable 和 Sass 的 variable 不是一个概念. 不要把它们放一起看待.

Sass 的 variable 是用来存变量的, 编辑完之后就没有.

CSS variable 是定义在 element 了, JS 是可以获取到和修改的. 总之完全不是一个世界的东西. 用途动机都不一样.

$primary-color: red;
$secondary-color: red; h1 {
color: $primary-color;
}
p {
color: $secondary-color;
}

定义变量是用 $ 符号, 使用就直接放去想用的地方就可以了.

编译完成后 css file

h1 {
color: red;
}
p {
color: red;
}

有了变量表达加分, 要批量换也容易, 修改加分.

Private Variable

$_private-variable: blue;

变量名字开头是下划线 _ 表示它是一个私有变量, 在 @use 的时候无法引用.

Default Variable Value

$primary-color: blue !default;

!defualt, 这样 @use 的时候可以 override.

当用于给 CSS variable 赋值

参考: Breaking Change: CSS Variable Syntax

直接把 Sass variable 赋值给 CSS variable 是错误的, 必须加上 #{}

另外当值有 quote 的时候 #{} 依然是错的, 需要用 meta.inspect()

Nested 嵌套

CSS 是平的

#hero-section h1 {
color: red;
}
#hero-section h1:hover {
color: black;
}
#hero-section h1:my-class {
color: yellow;
}
#hero-section p {
color: blue;
}

#hero-section 被重复了 3 次, #hero-section h1 被重复了 2 次

而且不容易看出它们的关系.

Sass 是可嵌套的, 它这样写.

#hero-section {
h1 {
color: red;
&:hover {
color: black;
}
&.my-class {
color: yellow;
}
}
> p {
color: blue;
}
}

& 是同时的意思.

这样就去除了重复的部分, 而且包在一起也增加了关系的表达.

它编辑出来就和上面 CSS 版本一样.

@keyframes

Sass 允许把 @keyframes 写到某个 style code 里面.

.container {
animation: dada 2s ease forwards; @keyframes dada {
100% {
background-color: blue;
}
}
}

compile 以后会被放到 root.

提醒: 因为最后是放到 root 的, 所以 keyframes 的名字不可以撞哦, 它可没有 scope 的概念, 只是简单的搬出去而已.

@media

media query 也不例外, 可嵌套

.container {
max-width: 100%;
@media (min-width: $breakpoint-sm) {
max-width: 540px;
}
}

效果

.container {
max-width: 100%;
}
@media (min-width: 576px) {
.container {
max-width: 540px;
}
}

parent selector

参考:

Stack Overflow – Can I check parent element has specific class in sass?

Docs – Parent Selector

把 & 写在后面. 它会生成如下的 selector

.blue 被放到了最前面, 变成了所谓的 "parent" 但其实是 ancestor. 这招 parent selector 也不是那么厉害, 一些小地方能用到罢了. 很多时候是不够用的.

@use (前生是 @import)

参考:

Stop using @import with Sass | @use and @forward explained

2020年的css周边之sass用法指南 @use和@forward 的部分.

早年是叫 @import 的, 后来换成 @use 了, 功能也改了一些.

@use 可以理解为 module / namespace, 它让我们可以把 CSS 代码分散到多个 file 做管理. 通过 @use 引入来使用.

基本用法

最常见的就是 _variable.scss 了

它的 file name 开头是下划线 _ 这表示这个 file 是需要被 @use 的, 所以 compiler 不会生成 _variable.css 文件.

它的使用方式是:

注意 @use 一定要放在顶部 (before style code, 如果 @use 前面是定义 variable 的话还 ok) , 它的 file name 不需要有下划线(_), 也不需要有 extension (.scss)

调用 variable 的时候需要配上 namespace (file name)

Change Namespace

和 JS 的 import 类似, 可以通过 as 关键字换名字

通过 as * 还能去掉 namespace 哦

Override Default Variable

$primary-color: blue !default;
@use "./variable" as * with (
$primary-color: yellow
);

使用关键字 with (variable : value) 可以覆盖 default variable.

@forward

参考: Sass Docs – @forward

它有点像 Angular 中的 re-export. import from a,b,c then export as d 这种方式.

比如有 variable1,2

做一个 forward import variable 1,2

@forward "./variable1" as first-*;
@forward "./variable2" as second-*;

as first-* 是添加 prefix, 防止撞名字, 如果没有撞名字的可能性,那可以不加

使用

@use "./forward";
h1 {
color: forward.$first-primary-color;
}
p {
color: forward.$second-primary-color;
}

此外它还有 show, hide 可以指定要 export 的 members, 它也可以通过 with override default variable

@use 和 @forward 的复杂例子

有 3 个 files: _core.scss, _base.scss, style.scss

core 是核心模块, base 是项目通用模块, style 是某个 page 的样式

_core.scss

@use "sass:list";
@use "sass:math"; @function map-get-next($map, $key) {
$keys: map-keys($map);
$values: map-values($map);
$index: list.index($keys, $key);
$count: length($keys);
$next-index: $index + 1;
@if ($next-index > $count) {
@return null;
}
@return list.nth($values, $next-index);
}
$breakpoint: null !default;
@function breakpoint($size) {
@return map-get($breakpoint, $size);
}
@function breakpoint-next($size) {
@return map-get-next($breakpoint, $size);
}
@mixin media-breakpoint-up($breakpoint) {
@media (min-width: breakpoint($breakpoint)) {
@content;
}
}
@mixin media-breakpoint-down($breakpoint) {
@media (max-width: breakpoint($breakpoint) - 0.02px) {
@content;
}
}
@mixin media-breakpoint-only($breakpoint) {
$current: breakpoint($breakpoint);
$next: breakpoint-next($breakpoint);
@if ($next == null) {
@media (min-width: $current) {
@content;
}
} @else {
@media (min-width: $current) and (max-width: $next - 0.02px) {
@content;
}
}
}
@mixin media-breakpoint-between($from-breakpoint, $to-breakpoint) {
@media (min-width: breakpoint($from-breakpoint)) and (max-width: breakpoint($to-breakpoint) - 0.02px) {
@content;
}
}

4 个 breakpoint 的 mixin 和一个 map-get-next 小方法, breakpoint 需要外部输入 variables.

_base.scss

$breakpoint: (
xs: 0,
sm: 640px,
md: 768px,
lg: 1024px,
xl: 1280px,
"2xl": 1536px,
); // 顺序是 as > show > with
// show 的名字是有加 prefix 的
@forward "./core" as core-* show core-map-get-next,
core-media-breakpoint-up with (
$breakpoint: $breakpoint
); // 需要用 @use 当前文档才可以调用到 core
// 不需要也不可以再设置 variables 了
@use "./core";
@mixin base-mixin {
@include core.media-breakpoint-up("lg") {
h1 {
width: 30px;
}
}
}

有几个点需要注意

1. @forward 使用 as, show/hide, with 的顺序是讲究的. as > show > with

2. show 在 as 之后, 所以 show 的名字需要加上 prefix

3. 如果当前 _base.css 也需要调用 core 方法的话, 还需要再 @use './core', @forward 不能让当前文档可调用 core 哦

4. 一个 module 只能有一个使用 with, 比如

@forward './core' as hide with

@forward './core' as show

@use './core'

上面只能在其中一个放 with. 不然会报错 This module was already loaded, so it can't be configured using "with".

style.scss

@use "./base" as *;

$obj: (
my-color: red,
my-width: 400px,
); @include core-media-breakpoint-up("lg") {
h1 {
width: core-map-get-next($obj, "my-color");
}
} @include base-mixin();

Operator

Sass 允许我们直接写 operator

h1 {
font-size: 10px + 20px;
}

虽然说 CSS 可以用 calc 但是上面这种写法在 compile 之后就变成 30px 了. 性能可定比较好.

@mixin and @include

mixin 类似 JS 的 function, 它可以用来封装一段 style code, 想要 copy paste 的时候就调用.

而且它可以用 parameter 做微调整哦.

@mixin some-repeat-style {
h1 {
color: red;
}
} @mixin some-repeat-property-style {
color: red;
} @include some-repeat-style();
@include name-repeat-style; /* 如果没有参数也可以不需要括弧 */ p {
@include some-repeat-property-style();
}

它就是把 mixin 内的 style code, copy paste 到 @include 的位置就对了.

效果

h1 {
color: red;
} p {
color: red;
}

搭配 parameter 和 default paramter value

@mixin my-mixin($extra-width: 100px) {
h1 {
font-size: 20px + $extra-width;
}

和 C# 类似 optional parameter 只能通过 assign default value 来实现. 不像 JS 写个 ? 就可以了.

所以最起码需要 assign 一个 null, 比如

@mixin func1($color: red) {
$color: if($color == null, red, $color);
color: $color;
} @mixin func2($color: null) {
@include func1($color);
} h1 {
@include func2;
}

底层 mixin 可以通过 ternay operator 判断是 null 就 assign default value. ternary operator 下面会详细讲.

@content 的用法

h1 {
@include font("display") {
color: red;
}
}

include 调用紧跟着一个对象.

@mixin font($type) {
@if $type == "display" {
font-size: 10rem;
@content;
} @else {
font-size: 1rem;
@content;
}
}

对象会被传入 @mixin 然后通过 @content paste 出来使用. 很适合用来做 extend 和 conditional (比如 media query)

甚至可以传参数沟通哦.

@function

mixin include 只是简单的 copy paste style code, function 则更像 JS, 它一般用来做算法逻辑等等.

@function my-function() {
@return 50px;
}

和 mixin 不同, 不管有没有 parameter, function 都要有括弧. 也必须有 return.

使用的时候不需要加 @include 之类的

h1 {
font-size: my-function() + 20px;
}

function 一般上会比较复杂, 会搭配 @if, @for, @each 这类 JS 语法来使用. 我目前没有用到这么复杂, 以后才讲.

@extend

继承, 比如某个 selector 想拥有另一个 selector 的 style code 的时候, 就可以用到.

.container {
width: 500px;
border: 2px solid red;
} .child-container {
@extend .container;
}

child-container 想拥有 .container 的 style. 可以用 @extend 表达

出来的效果是这样:

.container, .child-container {
width: 500px;
border: 2px solid red;
}

看不出什么厉害之处, 挺多只是表达好一些而已. 但是如果要扩展的话..

.child-container {
@extend .container;
background-color: red;
}

结果

.container, .child-container {
width: 500px;
border: 2px solid red;
} .child-container {
background-color: red;
}

这样结构上就加分了. 所以说 Sass 的目的就是让你的 CSS code 更加 manageable.

%placeholder

参考: Youtube – Sass Tutorials #19 - Placeholder Selectors

上面介绍的是 extend existing class, 但如果只是想抽象的话呢? 可以用 placeholder

%box {
outline: 1px solid black;
}
.box1 {
@extend %box;
}
.box2 {
@extend %box;
}

%box 是抽象的, 如果没用被引用, 它完全不会出现在 CSS 里面

效果

.container .box2, .container .box1 {
outline: 1px solid black;
}

You may not @extend selectors across media queries

%dada {
color: blue;
}
body {
@media (min-width: 1px) {
@extend %dada;
}
}

上面这样是不 ok 的, extend 必须在 media 里面

下面这样是 ok 的

body {
@media (min-width: 1px) {
%dada {
color: blue;
}
@extend %dada;
}
}

可以用 mixin 来替代, 参考: stackoverflow – Extending selectors from within media queries with Sass

当 @extend 遇上 pseudo

注意 %line 的位置. 如果它在 pseudo sbiling 就会错误 (多了一个 .test)

如果它在多一个 parent 就正常了. 多出来的 .test 没了.

当 @extend + override 遇上 @media

首先看看 CSS 的顺序

h1 {
color: pink;
} @media (max-width : 1024px) {
h1 {
color: lightgreen;
}
} h1 {
color: lightblue;
}

即便在 vw < 1024px 的情况下, h1 都是 lightblue. 最下面的代码赢.

而当我们 @extend + override 时

.aaa {
background-color: blue;
@media (width >= 1024px) {
background-color: red;
}
}
.bbb {
@extend .aaa;
background-color: yellow;
}

它出来的代码长这样

.aaa, .bbb {
background-color: blue;
}
@media (width >= 1024px) {
.aaa, .bbb {
background-color: red;
}
}
.bbb {
background-color: yellow;
}

最终 bbb 一定是 yellow, @extend 只是单纯把 selector 往之前的加而已 (参考这篇), 如果这不是你期望的. 那么可以改成用 mixin

@mixin aaa {
background-color: blue;
@media (width >= 1024px) {
background-color: red;
}
}
.bbb {
@include aaa;
background-color: yellow;
}

结果

.bbb {
background-color: blue;
background-color: yellow;
}
@media (width >= 1024px) {
.bbb {
background-color: red;
}
}

当 vw >= 1024px .bbb 是 red color.

Color Function

Sass 有自带一些 function。

首先 @use

@use 'sass:color';

color.complement 补色 (色轮 180°)

color.scale

控制色调和饱和度, 还有透明度

background-color: color.scale(red, $lightness: 0%); /* 起点 */
background-color: color.scale(red, $lightness: -100%); /* 黑色 */
background-color: color.scale(red, $lightness: 100%); /* 白色 */ background-color: color.scale(red, $alpha: -40%); /* 相等于 rgba(red, 0.6) */ background-color: color.scale(red, $saturation: 10%, $lightness: -10%); /* 调饱和度, 同时也可以调色调或透明 */

依据背景色调整 text color

@function text-color($color) {
@return if(color.lightness($color) > 40%, black, white);
} @mixin bg-and-text-color($color) {
background-color: $color;
color: text-color($color);
} .container {
@include bg-and-text-color(black);
}

通过 color.lightness 判断是亮色还是暗色

Get hue, saturation, lightness

$color: hsl(206, 94%, 28%);
$hue: color.hue($color); // 206
$saturation: color.saturation($color); // 94%
$lightness: color.lightness($color); // 28%

获取到色相, 饱和度, 明度

JS 语法

JS 有 object, array, for loop, if else, 等. Sass 也有, 只是比较少会用到, 除非你的项目真的很复杂, 或者你没有使用 Tailwind, Bootstrap 这种自带架构的框架或库.

这里介绍一些比较常会用到的

object & array

@use "sass:list";
@use "sass:map"; $obj: (
color: red,
size: 100px,
);
$obj-keys: map.keys($obj); // color, size
$obj-values: map.values($obj); // red, 100px $arr: red 100px; h1 {
color: map.get($obj, "color"); /* get property color */
color: map.get($obj, color); /* 不一定要 quote, 但 best practice 是有放的 */
background-color: list.nth($arr, 1); /* get first, not start with zero oh */
}

map dot 或 hypen 效果是一样的. e.g. map.get / map-get, map.keys / map-keys, map.has-key / map-has-key.

由于它的调用很丑, map.get($obj, color); 倒不如用 variable, $obj-color 更好一些.

所以通常会用 function 包装使用. 参考: Using SCSS maps as object - is it good?

$color: (
"red": red,
"yellow": yellow,
); @function color($key) {
@if not map.has-key($color, $key) {
@warn "Color `#{$key}` not found.";
}
@return map.get($color, $key);
}

调用

body {
background-color: color("red");
}

这样就比较好一些了.

注意: key 最好 quote 起来

$color-collection: (
white: hsl(0, 0%, 100%),
);
@function color($key) {
@return map.get($color-collection, $key);
}
.container {
color: color("white");
}

key = white 的时候, 上面这样 color 是出不来的.

一定要

$color-collection: (
'white': hsl(0, 0%, 100%),
);

sass 的对象是 immutable, 想修改 value 需要这样写

$obj: (
color: red,
size: 100px,
);
$obj : map.set($obj, 'color', blue);

if else & ternay operator

@function my-function($value) {
@if $value < 100 {
@return 50px;
} @else {
@return 10px;
}
} h1 {
width: my-function(30);
height: if(30 < 100, 50px, 10px); // ternary operator
}

当 if 遇上 array (Equality Operators)

@debug (5px 7px 10px) == (5px 7px 10px); // true
@debug (7px 5px 10px) == (5px 7px 10px); // false
@debug 7px 5px 10px == 5px 7px 10px; // 7px 5px false 7px 10px

顺序也要对。

没有括弧会有鬼。所以记得一定要括弧。

$values: 5px 7px 10px;
@debug $values == (5px 7px 10px); // true

for loop

from...to

@for $i from 0 to 3

result: [0, 1, 2], 从 0 开始到 2 结束. 3 不包含在内

from...through

@for $i from 0 through 3

result: [0, 1, 2, 3], 从 0 开始到 3 结束. 3 也包含在内

常见用法

$length: 3;
@for $i from 0 to $length {
h1:nth-child(#{$i + 1}) {
font-size: $i;
}
}

注:nth-child 括弧内需要 #{} 来引用 $i, font-size 值则不需要.

@each

$breakpoint: (
sm: 640px,
md: 768px,
lg: 1024px,
xl: 1280px,
2xl: 1536px,
);
@each $bp in $breakpoint {
.container-#{list.nth($bp, 1)} {
max-width: list.nth($bp, 2);
}
}

和 for loop 差不多, 也可以用来 each 出 object 的 key 哦, 它返回的是 array [key, value] 形式

array length

$breakpoints: "sm" "md" "lg";
$breakpoint-count: length($breakpoints);

array index of

@use "sass:list";

$breakpoints: "sm" "md" "lg";
$breakpoint-count: list.index($breakpoints, "sm");
.target {
width: $breakpoint-count; /* 1 */
}

注: 如果找不到返回值不是 -1 哦, 而是直接没有 width.

Rest Parameters

@use 'sass:list';

@function abc($values...){
@return list.nth($values, 2);
} $value: abc(red, yellow); * {
color: $value; // yellow
}

和 JS 类似,只是 点点点 在后面。

Nullish Coalescing

$value1: null;
$value2: $value1 or yellow; $value3: red;
$value4: $value3 or yellow; * {
color: $value2; // yellow
color: $value4; // red
}

CSS – Sass & SCSS的更多相关文章

  1. CSS & SASS & SCSS & less

    CSS & SASS & SCSS & less less vs scss https://github.com/vecerek/less2sass/wiki/Less-vs. ...

  2. CSS, Sass, SCSS 关系

    Sass(Syntactically Awesome Style Sheets) ,是一种css预处理器和一种语言, 它可以用来定义一套新的语法规则和函数,以加强和提升CSS. 它有很多很好的特性,但 ...

  3. 前端编码规范(4)—— CSS 和 Sass (SCSS) 规范

    CSS and Sass (SCSS) style rules ID and class naming ID和class(类)名总是使用可以反应元素目的和用途的名称,或其他通用名称.代替表象和晦涩难懂 ...

  4. CSS预处理器Sass(Scss)、Less、Stylus

    CSS 预处理编译器能让我成程序化其的方式编写CSS代码,可以引入CSS中没有的变量.条件.函数等特性,从而让代码更简单易维护,但一般按预处理器语法编写的代码无法直接在浏览器中运行,需用通过工具比如g ...

  5. CSS预处理器 Less Sass,Scss 编译 Sourcemap调试

    sass.less和stylus的安装使用和入门实践     SASS用法指南    Sass Basics CSS预处理器 css preprocessor 预处理器即preprocessor,预处 ...

  6. sass/scss 和 less的区别

    一. Sass/Scss.Less是什么? Sass (Syntactically Awesome Stylesheets)是一种动态样式语言,Sass语法属于缩排语法,比css比多出好些功能(如变量 ...

  7. vue2.0以上版本安装sass(scss)

    一.首先说明sass和scss的区别. 1.异同:1)简言之可以理解scss是sass的一个升级版本,完全兼容sass之前的功能,又有了些新增能力.语法形式上有些许不同,最主要的就是sass是靠缩进表 ...

  8. Sass & Scss & CSS3

    Sass & Scss & CSS3 Sass & Scss @mixin & @include & @import & variable https: ...

  9. 「Vue」vue-cli 3.0集成sass/scss到vue项目

    vue-cli 3提供了两种方式集成sass/scss: 创建项目是选择预处理器sass手动安装sass-loader创建项目选择预处理器sass$ vue create vuedemo? Pleas ...

  10. Less、Sass/Scss

    一.Less.Sass/Scss是什么? 1.Less: 是一种动态样式语言. 对CSS赋予了动态语言的特性,如变量.继承.运算.函数. Less 既可以在客户端上运行 (支持IE 6+, Webki ...

随机推荐

  1. TypeScript 学习笔记 — 类型补充void,any, tuple ,enum,nerver, Symbol , BigInt ,unknown(三)

    目录 空值void 及(与Null 和 Undefined的区别) 任意值Any 元组类型 枚举类型 常量枚举 never 类型 1. 函数无法到达终点 2.通常校验逻辑的完整性,可以利用 never ...

  2. [oeasy]python017_万行代码之梦_vim环境_复制粘贴

    继续运行 回忆上次内容 上次 保存运行一条龙 :w|!python3 %   我想 再多输出 几行 增加一下 代码量 可以吗?       添加图片注释,不超过 140 字(可选) 代码量 在正常模式 ...

  3. linux系统是未来_大小写敏感_case_sensitive_编程原生态

    修改 py 文件 回忆上次内容 上次尝试了 两个vim 同时打开 同一py文件 vim出现了Error 有各种选择     错误拼写 pront 导致 运行时 出现了NameError         ...

  4. Docker Compose 基本概要

    Docker Compose 基本概要 Compose 是一个用于定义和运行多容器 Docker 应用程序的工具.使用 YAML 文件来配置多个应用程序的服务,包括生产.暂存.开发.测试以及 CI 工 ...

  5. 概述C#中各种类型集合的特点

    在C#中,集合是用于存储和操作一组数据项的数据结构.这些集合通常位于 System.Collections 和 System.Collections.Generic 命名空间中.下面我将概述C#中几种 ...

  6. 对比python学julia(第一章)--(第一节)万事开头也不难

    自1989年被创立以后,历经30多年的发展,Python已经如日中天,在运维.大数据.云计算.web.科学计算上混的风生水起,并且于2020.2021年蝉联TIOBE年度编程语言首座.以至于,如今不会 ...

  7. 【MQTT】Mosquitto 入门案例

    参考博主StoneGeek的文章 https://www.cnblogs.com/sxkgeek/p/9140180.html 之前接触的是在应用程序之间的消息中间件技术 RabbitMQ, Kafk ...

  8. 【Mybatis】记录下一些问题

    报错信息: 找不到映射的结果Map 其实这里的包的名字和资源的名字都是正确的 但是啊,但是啊,在Mapper.xml上面的命名空间的声明上换行了,这就能导致Mybatis找不到这个资源: 我和同事看了 ...

  9. 【ActiveJdbc】05

    一.事务 通常在 Java ORM 中有一个显式连接或管理器对象(JPA 中的 EntityManager,Hibernate 中的 SessionManager 等). ActiveJDBC 中没有 ...

  10. 【PostgreSQL】01 环境搭建

    [PostgreSQL数据库安装] 数据库本体就没下本机了,直接挂服务器的Docker上面跑 docker pull postgres:9.4 创建容器并运行: docker run --name p ...