翻译 | 《JavaScript Everywhere》第13章 设置应用程序样式
写在最前面
大家好呀,我是毛小悠,是一位前端开发工程师。正在翻译一本英文技术书籍。
为了提高大家的阅读体验,对语句的结构和内容略有调整。如果发现本文中有存在瑕疵的地方,或者你有任何意见或者建议,可以在评论区留言,或者加我的微信:code
_maomao,欢迎相互沟通交流学习。
(σ゚∀゚)σ..:*☆哎哟不错哦
第13章 设置应用程序样式
猫王埃尔维斯·科斯特洛(Elvis Costello
)在1978
年的单曲《嘴唇服务》(Lip Service
)中嘲笑这句话:“不要表现得比我高,而要看着你的鞋子。“这种“亲吻”意味着叙述者只要亲吻某人的鞋子,就能察觉出他想要获得更高的社会地位,无论他们的西装多么考究,衣着多么高雅。
不管是好是坏,某些风俗是人类文化的重要组成部分,我们都习惯于接受这些类型的社交方式。考古学家甚至发现,旧石器时代的人类用骨头,牙齿,浆果和石头制作了项链和手镯。我们的衣服不仅可以起到保护人体免受各种元素侵害的功能目的,而且还可以与他人传递有关我们的文化、社会地位、利益等等的信息。
没有Web
的默认样式,Web
应用程序仍然可以正常工作,但是通过应用CSS
,我们可以更清晰地与用户通信。在本章中,我们将探讨如何使用CSS-in-JS
样式组件库将布局和样式引入我们的应用程序。这将使我们能够在可维护的、基于组件的代码结构中做出更实用、更美观的应用程序。
创建布局组件
应用程序的许多页面(在我们的情况下是全部)将共享一个通用布局。例如,我们应用程序的所有页面都将具有标题、侧边栏和内容区域(图13-1
)。
与其在每个页面组件中导入共享的布局元素,我们可以创建专门用于我们的布局的组件并将每个页面组件包装在其中。
图13-1
。页面布局的线框
为了创建我们的组件,我们将从创建一个新文件src/components/Layout.js
开始。在此文件中,我们将导入共享组件并布置内容。我们的React
组件函数将接收一个children
的属性,这将告诉我们在布局中哪里放置子元素的内容。
让我们在src/components/Layout.js
中创建我们的组件:
import React from 'react';
import Header from './Header';
import Navigation from './Navigation';
const Layout = ({ children }) => {
return (
{children} );
};
export default Layout;
现在在src/pages/index.js
文件中,我们可以将页面组件包装在新创建的Layout
组件中,以将共享布局应用于每个页面:
// import React and routing dependencies
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
// import shared layout component
import Layout from '../components/Layout';
// import routes
import Home from './home';
import MyNotes from './mynotes';
import Favorites from './favorites';
// define routes
const Pages = () => {
return (
{/* Wrap our routes within the Layout component */}
);
};
export default Pages;
最后一步是删除页面组件中或页面组件内的所有实例。例如,我们的src/pages/Home.js
文件现在将具有以下简化的代码:
import React from 'react';
const Home = () => {
return (
This is the home page
);
};
export default Home;
完成此操作后,你可以在浏览器中查看你的应用程序。在路由之间切换时,我们会在每个页面上看到我们的标题和导航链接。目前,它们尚未设置样式,并且我们的页面没有视觉布局。让我们在下一部分中探索添加样式。
CSS
级联样式表精确命名:它们是一组规则,允许我们编写Web
样式。样式为“层叠”,表示将呈现最后或最明确定义的样式。例如:
p {
color: green
}
p {
color: red
}
该CSS
会将所有段落呈现为红色,从而使颜色:绿色规则被覆盖。这是一个很简单的想法,但是为了避免错误,它产生了许多模式和技术。
BEM
(块元素修饰符),OOCSS
(面向对象CSS
)和Atomic CSS
等CSS
结构技术使用说明性的类命名来帮助作用域样式。诸如SASS
(语法很棒的样式表)和Less
(更精简的样式表)之类的预处理器提供了简化CSS
语法并启用模块化文件的工具。尽管它们各有千秋,但是CSS-in-JavaScript
为开发React
或其他JavaScript
驱动的应用程序提供了引人注目的用例。
那么CSS框架呢?
CSS
和UI
框架是开发应用程序的流行选择,这有充分的理由,它们提供了坚实的样式基础,并通过为常见的应用程序模式提供样式和功能来减少开发人员需要编写的代码量。折衷方案是使用这些框架的应用程序可能在视觉上变得相似,并且可能会增加文件包的大小。但是,这种权衡可能对你来说是值得的。我个人最喜欢使用React
的一些UI
框架是Ant Design
, Bootstrap
, Grommet
, 和 Rebass
CSS-in-JS
当我第一次遇到CSS-in-JS
时,我最初的反应很吃惊。我在Web
标准时代度过了我的Web
开发生涯的初期阶段。我继续倡导Web
开发的可访问性和合理的逐步增强。十多年来,“关注点分离”一直是我的网络实践的核心。因此,如果你像我一样,只是阅读“ CSS-in-JS
”会使你感到厌恶,那么你并不孤单。但是,一旦我进行了适当的(并且没有判断力的)尝试,我很快就被征服了。CSS-in-JS
使我们可以轻松地将我们的用户界面视为一系列组件,这是多年来我一直在尝试结合模块化技术和CSS
预处理器来完成的工作。
在本书中,我们将使用Styled Components
作为我们的CSS-in-JS
库。它快速、灵活,正在快速发展中,并且是最受欢迎的CSS-in-JS
库。Airbnb
,Reddit
,Patreon
,Lego
,BBC News
,Atlassian
等公司也使用它。
样式化组件库的工作方式是允许我们使用JavaScript
的模板字符串语法定义元素的样式。我们创建一个JavaScript
变量,该变量将引用HTML
元素及其关联的样式。由于听起来很抽象,所以让我们看一个简单的例子:
import React from 'react';
import styled from 'styled-components'
const AlertParagraph = styled.p`
color: green;
`;
const ErrorParagraph = styled.p`
color: red;
`;
const Example = () => {
return (
This is green.
This is red.
);
};
export default Example;
如你所见,我们可以轻松的确定样式范围。此外,我们将样式限定到该特定的组件。这有助于我们避免在应用程序的不同部分之间发生类名冲突。
创建一个按钮组件
现在我们对样式化组件有了基本的了解,让我们将它们集成到我们的应用程序中。首先,我们将为元素编写一些样式,这将使我们能够在整个应用程序中重用该组件。在前面的示例中,我们将样式与React/JSX
代码集成在一起,但是我们也可以编写独立样式的组件。首先,在src/components/Button.js
处创建一个新文件,从styled-components
中导入样式库,然后将可导出组件设置为模板字符串,如下所示:
import styled from 'styled-components';
const Button = styled.button` /* our styles will go here */ `;
export default Button;
放置好组件后,我们可以用一些样式填充它。添加一些基线按钮样式以及悬停和活动状态样式,如下所示:
import styled from 'styled-components';
const Button = styled.button`
display: block;
padding: 10px;
border: none;
border-radius: 5px;
font-size: 18px;
color: #fff;
background-color: #0077cc;
cursor: pointer;
:hover {
opacity: 0.8;
}
:active {
background-color: #005fa3;
}
`;
export default Button;
现在,我们可以在整个应用程序中使用按钮。例如,要在应用程序的主页上使用它,我们可以导入组件并在通常使用的任何位置使用元素。
在src/pages/home.js
中:
import React from 'react';
import Button from '../components/Button';
const Home = () => {
return (
This is the home page
);
};
export default Home;
这样,我们编写了一个样式化的组件,可以在应用程序中的任何地方使用它。这对于可维护性非常有用,因为我们可以轻松地找到样式并在我们的代码库中进行更改。此外,我们可以将样式化的组件与标记耦合在一起,从而允许我们创建小型、可重用和可维护的组件。
添加全局样式
尽管我们的许多样式将包含在各个组件中,但是每个站点或应用程序也具有一组全局样式(诸如CSS
重置,字体和基准颜色之类的东西)。我们可以创建一个GlobalStyle.js
组件来容纳这些样式。
这将与之前的示例有所不同,因为我们将创建样式表,而不是附加到特定HTML
元素的样式。为此,我们将从styled-components
导入createGlobalStyle
模块。我们还将导入normalize.css
库,以确保跨浏览器呈现一致的HTML
元素。最后,我们将为应用程序的HTML
主体和默认链接样式添加一些全局规则。
在src/components/GlobalStyle.js
中:
// import createGlobalStyle and normalize
import { createGlobalStyle } from 'styled-components';
import normalize from 'normalize.css';
// we can write our CSS as a JS template literal
export default createGlobalStyle` ${normalize}
*, *:before, *:after {
box-sizing: border-box;
}
body,
html { height: 100%;
margin: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
background-color: #fff;
line-height: 1.4;
}
a:link, a:visited { color: #0077cc;
}
a:hover, a:focus { color: #004499;
}
code,
pre {
max-width: 100%;
} `;
要应用这些样式,我们将它们导入到App.js
文件中,并在应用程序中添加元素:
import React from 'react';
import ReactDOM from 'react-dom';
// import global styles import GlobalStyle from '/components/GlobalStyle';
// import routes import Pages from '/pages';
const App = () => {
return (
);
};
ReactDOM.render( , document.getElementById('root'));
这样,我们的全局样式将应用于应用程序。在浏览器中预览应用程序时,你会看到字体已更改,链接具有新样式以及边距已删除(图13-2
)。
图13-2
我们的应用程序现在已应用了全局样式
组件样式
现在我们已经在应用程序中应用了一些全局样式,我们可以开始对单个组件进行样式化了。在此过程中,我们还将介绍应用程序的总体布局。对于我们样式化的每个组件,我们首先要从styled-components
导入样式库。然后,我们将一些元素样式定义为变量。最后,我们将在React
组件的JSX
中使用这些元素。
样式化组件命名
为了避免与HTML
元素发生冲突,必须将样式化组件的名称大写。
我们可以从src/components/Layout.js
开始,在这里我们将样式添加到应用程序布局的结构和标签中。
import React from 'react';
import styled from 'styled-components';
import Header from './Header';
import Navigation from './Navigation';
// component styles
const Wrapper = styled.div`
/* We can apply media query styles within the styled component */
/* This will only apply the layout for screens above 700px wide */
@media (min-width: 700px) {
display: flex;
top: 64px;
position: relative;
height: calc(100% - 64px);
width: 100%;
flex: auto;
flex-direction: column;
}
`;
const Main = styled.main`
position: fixed;
height: calc(100% - 185px);
width: 100%;
padding: 1em;
overflow-y: scroll;
/* Again apply media query styles to screens above 700px */
@media (min-width: 700px) {
flex: 1;
margin-left: 220px;
height: calc(100% - 64px);
width: calc(100% - 220px);
}
`;
const Layout = ({ children }) => {
return (
{children} );
};
export default Layout;
随着我们Layout.js
成分齐全,我们可以在我们Header.js
和Navigation.js
文件添加一些样式:
在src/components/Header.js
中:
import React from 'react';
import styled from 'styled-components';
import logo from '../img/logo.svg';
const HeaderBar = styled.header`
width: 100%;
padding: 0.5em 1em;
display: flex;
height: 64px;
position: fixed;
align-items: center;
background-color: #fff;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.25);
z-index: 1;
`;
const LogoText = styled.h1`
margin: 0;
padding: 0;
display: inline;
`;
const Header = () => {
return (
Notedly );
};
export default Header;
最后,在src/components/Navigation.js
中:
import React from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
const Nav = styled.nav`
padding: 1em;
background: #f5f4f0;
@media (max-width: 700px) {
padding-top: 64px;
}
@media (min-width: 700px) {
position: fixed;
width: 220px;
height: calc(100% - 64px);
overflow-y: scroll;
}
`;
const NavList = styled.ul`
margin: 0;
padding: 0;
list-style: none;
line-height: 2;
/* We can nest styles in styled-components */
/* The following styles will apply to links within the NavList component */
a {
text-decoration: none;
font-weight: bold;
font-size: 1.1em;
color: #333;
}
a:visited {
color: #333;
}
a:hover,
a:focus {
color: #0077cc;
}
`;
const Navigation = () => {
return (
);
};
export default Navigation;
应用这些样式后,我们现在有了一个完全样式化的应用程序(图13-3
)。展望未来,我们可以在创建单个组件时应用样式。
图13-3
。我们的应用程序已应用样式
结论
在本章中,我们向应用程序介绍了布局和样式。使用CSS-in-JS
库中的Styled Components
,我们可以编写简明扼要的CSS
样式。然后,可以将这些样式应用于单个组件,也可以应用于整个应用程序。在下一章中,我们将通过实现GraphQL
客户端并调用我们的API
来开发功能齐全的应用程序。
如果有理解不到位的地方,欢迎大家纠错。如果觉得还可以,麻烦你点赞收藏或者分享一下,希望可以帮到更多人。