Hermione


  • Home

  • Archives

webpack配置问题 - HappyPack (plugin for the loader '1' could not be found!)

Posted on 2019-03-20 | In 问题集

原配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length});
module: {
rules: [{
test: /\.(jsx|js)$/,
use: {
loader: 'happypack/loader?id=happyBabel',
query: {
presets: ['react', 'es2017'],
plugins: ['transform-object-rest-spread', "syntax-dynamic-import"]
}
},
exclude: /node_modules/
},{...}]
}
plugins: [
new HappyPack({
id: 'happyBabel',
threadPool: happyThreadPool,
loaders: ['babel-loader?cacheDirectory=true']

}),
...
]

版本

1
2
3
4
5
"babel-loader": "^7.1.5",
"happypack": "^5.0.1",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14"

将loader下query换到HappyPack中

修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module: {
rules: [{
test: /\.(jsx|js)$/,
loader: 'happypack/loader?id=happyBabel',
exclude: /node_modules/
},{...}]
}
plugins: [
new HappyPack({
id: 'happyBabel',
threadPool: happyThreadPool,
loaders: [{
path: 'babel-loader',
cache: true,
query: {
presets: ['react', 'es2017'],
plugins: ['transform-object-rest-spread', "syntax-dynamic-import"]
}
}]
}),
...
]

IntersectionObserver实现react列表滚动

Posted on 2019-03-18 | In 前端基础应用
前言

想法是在列表下方或上方添加一个div元素,当元素出现在浏览器视口,滚动列表。

用法
初始化
1
2
3
4
5
6
7
8
constructor(props) {
super(props);
this.ioNext = null;
this.nextContainer = null;
this.ioPrev = null;
this.prevContainer = null;
this.loadNextMore = this.loadNextMore.bind(this);
this.loadPrevMore = this.loadPrevMore.bind(this);
  • ioNext是下拉IntersectionObserver对象,ioPrev对应上拉
  • nextContainer是需要观察下拉时出现在浏览器视口的元素,prevContainer同理
创建元素
1
2
let loadNextMore = <div ref={div => {this.nextContainer=div;}}><Spin tip="loading..." className={styles['loading-tips']}  /></div>; 
let loadPrevMore = <div ref={div => {this.prevContainer=div;}}><Spin tip="loading..." className={styles['loading-tips']} /></div>;

将loadNextMore、loadPrevMore放在render中return就好,具体用法根据实际情况

监听元素行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
componentDidUpdate() {
if(this.nextContainer) {
this.ioNext = new IntersectionObserver(entry => {
if(window.innerHeight > entry[0].boundingClientRect.top) {
this.loadNextMore();
}
}, {});
this.ioNext.observe(this.nextContainer);
}
if (this.prevContainer) {
this.ioPrev = new IntersectionObserver(entry => {
if(entry[0].boundingClientRect.top > 0 && entry[0].boundingClientRect.top < window.innerHeight) {
this.loadPrevMore();
}
}, {});
this.ioPrev.observe(this.prevContainer);
}
}


loadPrevMore() {
//具体实现
}

loadNextMore() {
//具体实现
}
注意

上拉加载的情况,若直接替换state中渲染元素需考虑将上拉加载出来的数据向上偏移一定值。

【整理】JS DOM基本操作方法

Posted on 2019-03-12 | In js基础

面试的时候有问到DOM操作,全给忘了,整理一下。

DOM

Node类型

DOM1级定义了一个Node接口,该接口由DOM中所有节点类型实现。每个节点都有一个nodeType属性,用于表明节点类型。

属性
  • nodeType
  • nodeName
  • nodeValue
  • childNodes
    • 保存类数组对象NodeList
  • parentNode : 指向文档树中的父节点
    • 父节点有firstChild与lastChild属性,分别指向childNodes列表中的第一个和最后一个节点
  • nextSibling
  • previousSibling
  • ownerDocument: 指向整个文档的文档节点
节点操作方法
  • appendChild()
  • insertBefore()
  • replaceChild()
    • 接收两个参数:要插入的节点和要替换的节点
  • removeChild()
其他方法

所有节点共有的方法

  • cloneNode(): 用于创建节点副本
  • normalize(): 处理文档树中的文本节点
Document类型

Document类型表示文档,document对象是HTMLDocument的一个实例,表示整个HTML页面。document对象是window对象的一个属性,可以作为全局对象来访问。

特征
  • nodeType: 9
  • nodeName: #document
  • nodeValue: null
  • parentNode: null
属性
  • documentElement
  • body: 指向元素
  • doctype: 取得对<!DOCTYPE>的引用
  • title: 取得文档标题
  • URL
  • domain
方法
  • getElementById()
  • getElementsByTagName()
Element类型
  • nodeTye: 1
  • nodeName:
  • nodeValue
方法

主要是属性方法,自定义特性应加上“data-”前缀以便验证

  • getAttribute()
  • setAttribute()
  • removeAttribute()
  • attributes():返回属性的集合
  • createElement()
  • appendChild()
Text类型
  • nodeType: 3
  • nodeName: #text
  • nodeValue

DOM扩展

核心方法有两个,可以通过Document及Element类型的实例调用,接收css选择器为参数

  • querySelector()
  • querySelectorAll()
元素遍历方法
  • childElementCount: 返回子元素的个数
  • firstElementChild
  • lastElementChild
  • previousElementSibling
  • nextElementSibling

记录浏览器在地址栏按回车、F5、Ctrl+F5刷新网页的区别

Posted on 2019-03-02 | In 网络基础

看了 在浏览器地址栏按回车、F5、Ctrl+F5刷新网页的区别 一文,觉得很神奇,就想着验证一下(以请求百度首页为例)。

Firefox
在浏览器地址栏回车

Accept
Accept-Encoding
Accept-Language
Connection: keep-alive
Cookie
Host
Upgrade-Insecure-Requests
User-Agent

这是初次访问的请求头,缓存过期的情况没能实践成功,也就没法验证请求头中是否有If-Modified-Since这一字段。

F5刷新请求头

Accept
Accept-Encoding
Accept-Language
Cache-Control: max-age=0
Connection: keep-alive
Cookie
Host
Upgrade-Insecure-Requests
User-Agent

与上相比多了Cache-Control字段,值为max-age=0

Ctrl+F5刷新

Firefox请求头

Accept
Accept-Encoding
Accept-Language
Cache-Control: no-cache
Connection: keep-alive
Cookie
Host
Pragma: no-cache
Upgrade-Insecure-Requests
User-Agent

与上不同的是Cache-Controe值为no-cache

Chrome

与Firefox不同,Chrome三次请求的请求头都是一样的,与上Ctrl+F5请求头字段一致,可见Chrome不管怎样刷新,都不读取缓存,直接向服务器请求资源。

【整理】跨域的几种方式

Posted on 2019-02-21 | In 网络基础

jsonp

说说json与jsonp

jsonp原理是动态添加一个script标签,script标签的src属性是没有跨域限制的。

在访问的url里传入回调函数及参数。

缺点:

  • 只支持get不支持post
  • 只支持http请求这种情况,不能解决不同于两个页面之间如何进行JavaScript调用的问题
  • jsonp请求失败时不返回http状态码

CORS

HTTP访问控制(CORS)

cors请求分为简单请求与非简单请求

简单请求

若请求满足所有下述条件,则该请求可视为简单请求

  • 使用一下方法之一
    • get
    • head
    • post
  • Content-Type的值仅限于一下三者:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload对象均没有注册任何事件监听器;XMLHTTPRequestUpload对象可以使用XMLHttpRequest.upload属性访问
  • 请求中没有使用ReadableStream对象
Read more »

原生js实现图片轮播

Posted on 2019-02-20 | In 前端基础应用

前言

寒假在家随便做个网站demo的时候用到了antd的轮播,当时没有找到左边有上下页按钮的示例,回到学校,发现实验的项目也有轮播,不过是用angular做的,这个轮播只有上下页按钮,没有antd的中间可任意选择第几章图片的工具,就想着自己用js实现一下轮播功能,把这两种功能都合起来。

感谢 十五分钟用 JavaScript 基础写一个图片轮播效果 + 思路详解 提供的思路,在实现的时候基本是以上博客的思想,有改动。

主要从三个方面记录自己的实现过程,有部分自己的想法,也有待优化的部分。

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="img-content">
<div class="img-carousel">
<div class="img-container"><img src="./images/1.jpg" alt=""></div>
<div class="img-container"><img src="./images/2.jpg" alt=""></div>
<div class="img-container"><img src="./images/3.jpg" alt=""></div>
</div>
<div class="arrow">
<span class="left-arrow">&lt;</span>
<span class="right-arrow">&gt;</span>
</div>

<div class="dot-choose">
<span class="dot" style="background-color: #D4D4D4"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>

html分三个部分,图片显示、左右方向键以及底部四个圆角矩形可供任意选择图片。
(习惯在img标签外面套一层div)

Read more »

React知识点整理

Posted on 2019-01-13 | In 学习笔记

初入React

JSX语法

  • 定义标签时,只允许被一个标签包裹
  • 标签一定要闭合
  • 注释被{}包起来

React组件

  • 无状态组件创建时始终保持了==一个实例==
  • 有状态组件创建几次组件就会创建几次实例

React数据流

state
  • setState是==异步==方法
    props
  • props本身是不可变的(==readonly==)
  • ==defaultProps==静态变量可以定义props默认配置(==默认类型==)

    1
    2
    3
    4
    static defaultProps = {
    classPrefix: 'tabs',
    onChange: () => {},
    };
  • React中有一个内置的prop:children,代表组件的子组件集合

  • JavaScript不是强类型的语言,React对此做了改进,==propTypes==用于规范props的类型与必要状态(==类型检查==)。
    1
    2
    3
    4
    5
    6
    7
    8
    static propTypes = {
    tab: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.node,
    ]).isRequired,
    order: React.PropTypes.string.isRequired,
    disble: React.PropTypes.bool,
    };
Read more »

ant design修改默认样式

Posted on 2018-12-07 | In 前端基础应用

将ant design文件编译成less文件,首先需安装less、less-loader

版本信息
1
2
3
4
5
"antd": "^3.13.4",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"css-loader": "^2.1.0",
"style-loader": "^0.23.1",
.babelrc配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"presets": [
"env",
"latest",
"react",
"stage-0"
],
"plugins":[
"transform-runtime",
"transform-object-rest-spread",
[
"import", {
"libraryName": "antd",
"style": true
}
]
]
}
webpack module
1
2
3
4
5
6
7
8
9
10
11
12
13
{
test: /\.less$/,
use: ['style-loader', 'css-loader', {
loader: 'less-loader',
options: {
modifyVars: {
"primary-color": "#169BD5",
"link-color": "#169BD5"
},
javascriptEnabled: true
}
}]
}

与后台进行通信webpack配置

Posted on 2018-11-09 | In 前端基础应用

一直不清楚做项目的时候前台怎么和后台进行通信,虽然知道可以通过ajax请求后台数据,但是不知道在具体项目中怎么运用的,正好自己搭项目的时候也遇到了这个问题,简单记录一下。

起因是webpack可以自己指定port(本地代码,host为http://localhost:port),并将文件打包,运行在指定的host上面。同时,后台也指定了程序运行的端口号。若前台指定的端口号和后台一样,肯定会有错误,若指定不同端口号,请求的url又跨域了,此时的做法是在webpack配置上加上一个devserver配置,加上一个代理

1
2
3
4
5
6
7
8
9
10
devServer: {
proxy: {
'/api/v1': 'http://localhost:8025',
},
contentBase: [path.join(__dirname, "dist")],
compress: true,
historyApiFallback: true,
hot: true,
port: port
},
配置 说明
proxy 请求到 /api/v1 会被代理请求到http://localhost:8025/api/v1
contentBase 告诉服务器从哪个目录内容提供文件
compress 一切服务都启用gzip压缩
historyApiFallback 默认禁用404响应被替代为index.html
hot 启用webpack的模块热加载功能(必须有 webpack.HotModuleReplacementPlugin 才能完全启用 HMR)
port 指定要监听请求的端口号

详细配置见 devserver

webpack.config.js文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
const path = require('path');
const webpack = require('webpack');

const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlwebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackIncludeAssetsPlugin = require('html-webpack-include-assets-plugin');
const OpenBrowerPlugin = require('open-browser-webpack-plugin');

const port = 8026;
const host = `http://localhost:${port}/`;

module.exports = {
entry: {
bundle: './src/index.js',
vendor: [
'classnames',
'redux',
'redux-thunk',
'redux-immutable',
'redux-actions',
'react-router',
'react-router-dom',
'history/createBrowserHistory'
]
},
output: {
path: path.resolve(__dirname, "dist"),
filename: 'js/[name].js',
chunkFilename: 'lib/[name].min.js',
publicPath: host
},

resolve: {
modules: [
"node_modules",
path.resolve(__dirname, "src")
],
extensions: [".js", ".jsx", ".json", ".css", ".scss"]
},

mode: 'development',
devtool: 'eval-source-map',

devServer: {
contentBase: './src',
historyApiFallback: true,
inline: true,
open: true,
hot: true,
compress: true,
port: port
},

module: {
rules: [{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
query: {
presets: ['react', 'es2017'],
plugins: ['transform-object-rest-spread', "syntax-dynamic-import"]
}
},
exclude: /node_modules/
},{
test: /\.scss$/,
use: ['style-loader', 'css-loader?modules', {
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({ browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8'] })
]
}
}, 'sass-loader']
},{
test: /\.less$/,
use: ['style-loader', 'css-loader', {
loader: 'less-loader',
options: {
modifyVars: {
"primary-color": "#169BD5",
"link-color": "#169BD5"
},
javascriptEnabled: true
}
}]
},{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},{
test: /\.(?:png|jpg|gif)/,
loader:'url-loader?limit=8192&name=image/[hash].[ext]'
},{
test: /\.svg$/,
loader: 'svg-url-loader'
}]
},

devServer: {
proxy: {
'/api/v1': 'http://localhost:8025',
},
contentBase: [path.join(__dirname, "dist")],
compress: true,
historyApiFallback: true,
hot: true,
port: port
},

plugins: [
// new webpack.optimize.CommonsChunkPlugin({
// names: ['vendor'],
// filename: 'lib/[name].min.js',
// }),
new webpack.optimize.SplitChunksPlugin({
cacheGroups: {
commons: {
chunks: 'initial',
minChunks: 2,
maxInitialRequetst: 5,
minSize: 0
},
vendor: {
test: /node_modules/,
chunks: 'initial',
name: 'vendor',
priority: 10,
enforce: true
}
}

}),
new CopyWebpackPlugin([{
from: 'node_modules/antd/dist/antd.min.js',
to: '/lib'
},{
from: 'node_modules/react/cjs/react.development.js',
to: '/lib'
},{
from: 'node_modules/react-dom/cjs/react-dom.development.js',
to: '/lib'
}]),

new HtmlwebpackPlugin({
filename: 'index.html',
template: 'src/index.ejs',
title: 'RShare'
}),

new HtmlWebpackIncludeAssetsPlugin({
assets: [
'lib/react-dom.development.js',
'lib/react.development.js',
'lib/antd.min.js'
],
append: false
}),
new OpenBrowerPlugin({
url: host
}),
]
}

伪元素实现文字左右横线

Posted on 2018-10-11 | In 前端基础应用

效果如下
image

html
1
<p className={styles['title']}>Sign in</p>
css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.title {
position: relative;
color: $gray-color-1;
text-align: center;
margin-bottom: 10px;

font-family: $decoration-text;
font-size: 28px;

&:before {
content: '';
position: absolute;
top: 50%;
/*background: $gray-color-8;*/
border-bottom: 1px solid $gray-color-8;
width: 35%;
height: 1px;
left: -1%;
}

&:after {
content: '';
position: absolute;
top: 50%;
/*background: $gray-color-8;*/
border-bottom: 1px solid $gray-color-8;
width: 35%;
height: 1px;
right: 1%;
}
}

主要是利用:before与:after伪元素,为横向预留位置

利用position将伪元素与主元素定位,利用布局将其居中显示,然后划线,background与border均可。

1234

张倩倩

36 posts
10 categories
19 tags
GitHub
© 2020 张倩倩
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4