1 | # css
|
2 | ## 《css世界》基于“流”的css布局
|
3 | ### 无宽度,无图片,无浮动
|
4 | - #### 无宽度
|
5 | 为何要无宽度?
|
6 | 表现为“外部尺寸”的块级元素一旦设定了宽度,流动性就失去了。
|
7 | 减少代码,减少维护,减少计算。
|
8 | 解决方案:
|
9 | ```css
|
10 | container: {
|
11 | width: 100%;
|
12 | max-width: 500px;
|
13 | }
|
14 | ```
|
15 | ```css
|
16 | container: {
|
17 | width: calc(100vw - 500px);
|
18 | }
|
19 | ```
|
20 | - #### 无图片
|
21 | 解决方案:
|
22 | - svg
|
23 | - canvas 画,图片高清,且便于实现动画效果,
|
24 | - iconfont图标字体的引入。
|
25 | - #### 无浮动
|
26 | 彻底摆脱看不懂,难以控制的`float:left`.
|
27 | 解决方案:
|
28 | - flex弹性布局 ,bootstrapt/antd 等优秀的库同样基于flex进行栅格布局.[can i use](https://caniuse.com/#search=flex)
|
29 | - grid网格布局,比flex更加优秀的布局.[can i use](https://caniuse.com/#search=grid)
|
30 |
|
31 | ### 布局
|
32 | - flex 弹性布局
|
33 | 简单易用,适用于移动端不同浏览器宽度的一种方案
|
34 | ```css
|
35 | container: {
|
36 | display: flex | inline-flex;
|
37 | flex-director: flex-direction: row | row-reverse | column | column-reverse;
|
38 | justify-content: flex-start | flex-end | center | space-between | space-around;
|
39 | align-items: flex-start | flex-end | center | baseline | stretch;
|
40 | flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
|
41 | }
|
42 | ```
|
43 | - grid 网格布局
|
44 | 面向未来的css布局方案
|
45 | ```css
|
46 | container: {
|
47 | display: grid | inline-grid | subgrid;
|
48 | grid-template-areas:
|
49 | "1fr header . 1fr"
|
50 | "main main . sidebar"
|
51 | "footer footer footer footer";
|
52 | grid-gap: <line-size> <line-size>;
|
53 | }
|
54 |
|
55 | ### css工程化
|
56 | - 工具
|
57 | - less sass(scss) stylus
|
58 | 嵌套规则,颜色命名,
|
59 | - postcss
|
60 | - Autoprefixer 自动兼容性写法工具
|
61 | usage: 项目目录下新建`.postcssrc`文件
|
62 | ```json
|
63 | {
|
64 | "plugins": {
|
65 | "autoprefixer": true,
|
66 | }
|
67 | }
|
68 | ```
|
69 | - postcss-modules 自动隔离组件内的选择器
|
70 | - 公共样式
|
71 | ```css
|
72 | //公共颜色
|
73 | @education1: #38c78c;
|
74 | @lock: #5BB2EF;
|
75 | @daocheng-red: #ca1523;
|
76 | @btn-red: #E24647;
|
77 |
|
78 | //公共字体
|
79 | @font-face {
|
80 | font-family: "Reem Kufi";
|
81 | src: url("../../assets/font/a.woff");
|
82 | }
|
83 |
|
84 | //公共图标字体
|
85 | svg{
|
86 | &.icon{
|
87 | width: 1em; height: 1em;
|
88 | vertical-align: -0.15em;
|
89 | fill: currentColor;
|
90 | overflow: hidden;
|
91 | }
|
92 | }
|
93 |
|
94 | // 公共动画样式
|
95 | @keyframes shake {
|
96 | 10%, 90% {
|
97 | -webkit-transform: translate3d(-1px, 0, 0);
|
98 | transform: translate3d(-1px, 0, 0);
|
99 | }
|
100 | 20%, 80% {
|
101 | -webkit-transform: translate3d(2px, 0, 0);
|
102 | transform: translate3d(2px, 0, 0);
|
103 | }
|
104 | 30%, 50%, 70% {
|
105 | -webkit-transform: translate3d(-4px, 0, 0);
|
106 | transform: translate3d(-4px, 0, 0);
|
107 | }
|
108 | 40%, 60% {
|
109 | -webkit-transform: translate3d(4px, 0, 0);
|
110 | transform: translate3d(4px, 0, 0);
|
111 | }
|
112 | }
|
113 | ```
|
114 |
|
115 | # javascript
|
116 | - 传参
|
117 | ```javascript
|
118 | // 以对象形式传参,可不分先后
|
119 | function a(args){
|
120 | const {
|
121 | name,
|
122 | bio
|
123 | } = args
|
124 | bio = (bio = undefined ? "" : bio);
|
125 | name = (name = undefined ? "" : name);
|
126 | return
|
127 | }
|
128 | a({name: 'peng',bio: 'code'})
|
129 | ```
|
130 | - callback hell es6帮你告别回调地狱
|
131 | ```javascript
|
132 | //利用jq 先拿url_a数据,成功后再拿url_b数据,成功后再拿url_c数据
|
133 | $.ajax({
|
134 | url:url_a,
|
135 | data,
|
136 | successful: function(data_a){
|
137 | $.ajax({
|
138 | url:url_b,
|
139 | data:data_a,
|
140 | successful: function(data_b){
|
141 | $.ajax({
|
142 | url:url_c,
|
143 | data:data_b,
|
144 | successful: function(data_c){
|
145 | $(this).addClass(data_c);
|
146 | }
|
147 | })
|
148 | }
|
149 | })
|
150 | }
|
151 | })
|
152 | // 利用es7 async/await 异步加载
|
153 | let getData = e => {
|
154 | const {url,data} = e
|
155 | new Promise((resolve,reject)=>{
|
156 | fetch(url,{data})
|
157 | .then(res=>res.json)
|
158 | .then(json=>resolve(json))
|
159 | })
|
160 | }
|
161 | let data_a = await getData({url:url_a,data:data})
|
162 | let data_b = await getData({url:url_b,data:data_a})
|
163 | let data_c = await getData({url:url_c,data:data_b})
|
164 | await console.log(data_c)
|
165 | ```
|
166 | - addeventlistener事件绑定 与 debounce防抖
|
167 | 简单来说,当为浏览器body元素绑定scroll事件之后,监听屏幕滚动事件,调用函数,仅仅只是简单下移100px,浏览器却执行了上百次绑定的函数的调用,这种高消耗性能,在移动端则会出现卡屏现象,这个时候需要为绑定的函数添加
|
168 | `document.body.addEventListener(event,_debounce(handEvent,250),false)`
|
169 | - jquery 替代方案
|
170 | ```js
|
171 | let $ = selector => {
|
172 | return document.querySelector(selector)
|
173 | }
|
174 | $('div') work well
|
175 | ```
|
176 |
|
177 | # 自动化工具
|
178 | - webpack3.10 健全,适合大型项目构建
|
179 | - rollup 适合打包npm模块,react就是用它打包的。
|
180 | - parcel 0配置,速度快,适合开发者环境下使用
|
181 | - gulp 基于nodejs流,好像适合单个文件less=>css , coffeescript=>javascript转换,代码,图片压缩。
|
182 |
|
183 | # 代码自动化检测
|
184 | - jslint
|
185 | - eslint
|
186 |
|
187 | # 代码冲突,修改,合并
|
188 | - vscode可以看,选择保存传入代码/本地代码,git status -s 同样可以查看冲突文件
|
189 | ![](https://code.visualstudio.com/assets/docs/editor/versioncontrol/merge-conflict.png)
|
190 |
|
191 | # react@16.2.0
|
192 | - jsx语法 js里面写html标签必备语法。可视化,需要配合babel进行jsx语法转换
|
193 | ```jsx
|
194 | const element = <h1>Hello, world!</h1>;
|
195 | ```
|
196 | - 渲染元素,通过render函数将jsx代码渲染到dom节点上面,
|
197 | ```jsx
|
198 | const element = <h1>Hello, world</h1>;
|
199 | ReactDOM.render(
|
200 | element,
|
201 | document.getElementById('root')
|
202 | );
|
203 | ```
|
204 | react 只会更新需要更新的dom节点
|
205 | ```jsx
|
206 | function tick() {
|
207 | const element = (
|
208 | <div>
|
209 | <h1>Hello, world!</h1>
|
210 | <h2>
|
211 | It is{' '}
|
212 | {new Date().toLocaleTimeString()}.
|
213 | </h2>
|
214 | </div>
|
215 | );
|
216 | ReactDOM.render(
|
217 | element,
|
218 | document.getElementById('root')
|
219 | );
|
220 | }
|
221 |
|
222 | setInterval(tick, 1000);
|
223 | ```
|
224 | ![](https://reactjs.org/granular-dom-updates-c158617ed7cc0eac8f58330e49e48224.gif)
|
225 |
|
226 | - Components与Props,翻译过来就是组件与属性,由于代码是英文构成, 为了便于理解,有必要知道英文
|
227 | ```jsx
|
228 | function Welcome(props) {
|
229 | return <h1>Hello, {props.name}</h1>;
|
230 | }
|
231 | const element = <Welcome name="Sara" />;
|
232 | ReactDOM.render(
|
233 | element,
|
234 | document.getElementById('root')
|
235 | );
|
236 | ```
|
237 | 上面代码有助于理解父组件如何将数据传递给子组件,鉴于react是基于单向数据流设计的,所以之能将数据从上之下传递,
|
238 | ```jsx
|
239 | function Welcome(props) {
|
240 | return <h1>Hello, {props.name}</h1>;
|
241 | }
|
242 | function App() {
|
243 | return (
|
244 | <div>
|
245 | <Welcome name="Sara" />
|
246 | <Welcome name="Cahal" />
|
247 | <Welcome name="Edite" />
|
248 | </div>
|
249 | );
|
250 | }
|
251 | ReactDOM.render(
|
252 | <App />,
|
253 | document.getElementById('root')
|
254 | );
|
255 | ```
|
256 | 以上实现了代码的复用,props是不可修改的。
|
257 | - state 以及 react的生命周期。
|
258 | ```jsx
|
259 | class Clock extends React.Component {
|
260 | constructor(props) {
|
261 | super(props);
|
262 | this.state = {date: new Date()};
|
263 | }
|
264 | componentDidMount() {
|
265 | //某个时刻执行,忘了
|
266 | }
|
267 | componentWillUnmount() {
|
268 | //某个时刻执行,忘了
|
269 | }
|
270 | render() {
|
271 | return (
|
272 | <div>
|
273 | <h1>Hello, world!</h1>
|
274 | <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
|
275 | </div>
|
276 | );
|
277 | }
|
278 | }
|
279 | ```
|
280 | - 处理事件
|
281 | ```jsx
|
282 | class Toggle extends React.Component {
|
283 | constructor(props) {
|
284 | super(props);
|
285 | this.state = {isToggleOn: true};
|
286 |
|
287 | // This binding is necessary to make `this` work in the callback
|
288 | this.handleClick = this.handleClick.bind(this);
|
289 | }
|
290 |
|
291 | handleClick() {
|
292 | this.setState(prevState => ({
|
293 | isToggleOn: !prevState.isToggleOn
|
294 | }));
|
295 | }
|
296 |
|
297 | render() {
|
298 | return (
|
299 | <button onClick={this.handleClick}>
|
300 | {this.state.isToggleOn ? 'ON' : 'OFF'}
|
301 | </button>
|
302 | );
|
303 | }
|
304 | }
|
305 |
|
306 | ReactDOM.render(
|
307 | <Toggle />,
|
308 | document.getElementById('root')
|
309 | );
|
310 | ```
|
311 | - 有条件的渲染某些元素
|
312 | ```jsx
|
313 | function WarningBanner(props) {
|
314 | if (!props.warn) {
|
315 | return null;
|
316 | }
|
317 | return (
|
318 | <div className="warning">Warning!</div>
|
319 | );
|
320 | }
|
321 | class Page extends React.Component {
|
322 | constructor(props) {
|
323 | super(props);
|
324 | this.state = {showWarning: true}
|
325 | this.handleToggleClick = this.handleToggleClick.bind(this);
|
326 | }
|
327 | handleToggleClick() {
|
328 | this.setState(prevState => ({
|
329 | showWarning: !prevState.showWarning
|
330 | }));
|
331 | }
|
332 | render() {
|
333 | return (
|
334 | <div>
|
335 | <WarningBanner warn={this.state.showWarning} />
|
336 | <button onClick={this.handleToggleClick}>
|
337 | {this.state.showWarning ? 'Hide' : 'Show'}
|
338 | </button>
|
339 | </div>
|
340 | );
|
341 | }
|
342 | }
|
343 | ReactDOM.render(
|
344 | <Page />,
|
345 | document.getElementById('root')
|
346 | );
|
347 | ```
|
348 | - 状态提升 听名字挺高级,其实就一个作用,便于子组件调用父亲,
|
349 |
|
350 | - react-router-dom react的前台路由配套设施
|
351 | - react-mobx,mobx 或者,react-redux,redux,,react状态管理,前面说了,react是基于单向数据流设计的,所以看下图形象说明所有问题
|
352 | ![](https://cdn.css-tricks.com/wp-content/uploads/2016/03/redux-article-3-03.svg)
|
353 | 通过最顶点store保存所有数据,子组件若想改变父组件状态,只能通过修改store内部数据,然后数据从顶部层层流向底部直至父组件。
|
354 | 有没有觉得react的单向数据流与angular和vue的双向绑定,在业务逻辑上面要清晰的多?看起来单向数据流多么麻烦,但是在浏览器内部仅仅只是一瞬间完成。
|
355 |
|
356 | # 前端工程化构建
|
357 | - 大型项目方案 react + webpack + react-router-dom + mobx + react-mobx
|
358 | - 标配 react create-react-app 脚手架
|
359 | - 标配 vue-cli 脚手架
|
360 | - 屌丝版0配置 parcel + postcss + less + autoPrify
|
361 | parcel默认自带babel转换语法,所以不需要再配置。
|