giscyw / blog Goto Github PK
View Code? Open in Web Editor NEW写博客的地方
写博客的地方
1.敬畏上线
所有的问题在测试的时候最好发现并且解决,而且是要自己主动发现。例如,项目上线之前,自己要在测试中mock可变数据来测试各种情况,不管是由于接口数据的可变性导致的多种场景,还是兼容性问题,等等,都是要马上发现并解决
2.对专业前后领域的理解
做业务的程序员必须要具备M型的能力,不仅要知道前端,还需要知道往前的业务,往后的后端逻辑和技术,如何能起到一个协调的角色,那确实很难得可贵,比技术本身的能力更加重要
3.先做起来
看到一个新的技术或者框架之类的,先用再说,要在用的过程中去感受它并调整自己对它的理解。
最近遇到两种代码报错的情况,一是我拉新的项目,跑起来之后在我这边报错,一种是我的项目本地build没有问题,服务器上构建就失败了。
前者是我执行了npm i,然后某个包安装了最新小版本,这个小版本的包本身存在错误。
后者是机器执行了npm i,然后某个包安装了最新小版本,这个小版本的包本身存在错误。
前者我们可以通过npm ci来解决,后者通过上传package-lock.json来解决
packagelock.json文件是需要上传git
该文件是用来避免在生产环境中因版本导致的构建错误或者运行时错误
场景:
但是我本地項目打包正常,線上的出錯,可能由於本地版本和線上版本不一致導致(某個小版本出現的 bug
)的。通過查看package.json
配置的 clipboard: "^2.0.4"
,線上實際安裝版本是 2.0.7
,而我本地實際安裝版本是 2.0.6
因此定位到 2.0.7
出現的 “問題”。这个时候你不能在package.json中固定clipboard: "2.0.4"
,最好还是在pakcage.lock.json中固定。因为
packagelock.json 是锁定包的依赖树版本的Package.json是锁住单个包的大版本
首次npm i会根据package.json安装并生成packagelock.json,之后的npm i都会根据packagelock.json安装;npm i 某个包会更新package.json.
用npm ci还是npm install
npm ci首先会自动删除 node_modules,根据 package-lock.json
安装依赖,不会修改你的 package-lock.json
,不能单独装包。
一般安装新的某个包用npm install,持续集成工具中更推荐是用 npm ci
,保证构建环境的准确性
npm cache clean –force作用
Node模块的安装过程是这样的:
如何解决package-lock.json的冲突
参考https://juejin.cn/post/7000179306764714020#heading-2
1.移动端如何调试
2.线上问题如何定位与调试
3.浏览器端如何调试
charles本地调试之map和rewrite功能
移动端前端开发调试
前端调试的最佳实践
Whistle 开发调试最佳实践
1.闪屏问题
2.页面宽度拉伸问题
3.点击无响应问题
4.上层数据更新了 底层组件没有更新
方法一 :使用属性 -webkit-text-stroke
对于该属性,只支持设置描边宽带和颜色,无法指定描边是外描边,还是内描边,还是居中描边,默认为居中描边。
.stroke {
-webkit-text-stroke: 2px red;
}
如果要实现外描边的效果,可以使用-webkit-text-stroke描边文字和非描边文字相互重叠覆盖的方法模拟,代码如下:
.strok-outside {
position: relative;
z-index: 0;
font-size: 40px;
}
.strok-outside::before {
content: attr(data-text);
position: absolute;
-webkit-text-stroke: 2px red;
z-index: -1;
}
重叠描边
方法二 :使用属性 text-shadow 该方法利用多层文字阴影模拟外描边效果,代码如下:.strok-outside {
text-shadow: 0 1px red, 1px 0 red, -1px 0 red, 0 -1px red;
}
但是,实际上,该方法实现的效果,并不是真正的外描边效果。因为一个矩形四面投影的时候,四个角实际上会有空隙,所以,描边会有缺角,并不是完全包裹,在描边越宽的情况下越明显。如果设计师要求较高,可以通过上述【方法一】来实现。
参考:
Safari HTML5 video element doesn't emit canplay event unless you're YouTube · Issue #1686 · video-dev/hls.js
video 移动端canplay不触发 - 掘金
H5 Video踩坑记录 | springleo's blog
HTML5 Audio & Video - 兼容性总结(一) - 掘金
javascript - 移动端 HTML5 video 视频兼容性问题 - SegmentFault 思否
load promise doesn't resolve on iOS Safari · Issue #2483 · shaka-project/shaka-player
javascript - HTML5 Video loadeddata event does not work in IOS Safari - Stack Overflow
其实这种问题应该是某个自组件没有重新渲染,我们可以从父组件开始打印改变的state,只要state改变了,ui没有改变,就看使用该state作为属性的组件,很可能里面的依赖有问题
首先看是后端问题还是前端问题;
后端问题判断:
参考:
线上崩了?一招教你快速定位问题!
前端开发调试最佳实践
前端线上故障响应方法
如何让调试线上 JS 报错像调试本地源码一样优雅?
前端项目线上出现紧急的bug怎么处理
2022年了,该学会用VSCode debug了
在 VS Code 和 Chrome 中调试
《**React 开发**纲领》**读完这份纲领,发现自己在react开发中存在了一些问题,主要总结如下:
我们在开发中经常用setState来设置变量,可以这样做:通过setState得到大的data,然后其他可以通过推导计算出的变量,我们可以有以下几种方式
一般,如果h不是有很多地方复用的话,就直接直接第一种;如果很多地方复用或者计算得到的表达式很长或者我是想用一个变量来命名它(这样容易看懂),可以使用第二和第三种
给组件设置属性的时候,只需要组件需要的属性,比如属性是data.width和data.height,我们不必把整个data设置为组件的属性。为了避免掉入这种坑,最好将基本类型(boolean
, string
, number
等)作为 props 传递。(传递基本类型也能更好的让你使用 React.memo
进行优化)。
组件应该仅仅只了解和它运作相关的内容就足够了。应该尽可能地与其他组件产生协作,而不需要知道它们是什么或做什么。如果我们设置组件的属性为data,那这样组件就会因为这个data产生协作了,正常的思维应该是,我(组件)是这样的,你就按我这样传吧。
这样做的好处是,组件间的耦合会更松散,依赖程度会更低。低耦合更利于组件修改,替换和移除,而不会影响其他组件。
当然如果你是通过data一个属性来表示组件的数据源属性,可以把需要的数据放到data里面。
也就是单一职责原则
检查组件的 state,props 和 hooks,以及组件内部声明的变量和方法(不应该太多)。问问自己:是否这些内容必须组合到一起这个组件才能工作?如果有些不需要,可以考虑把它们抽离到其他地方,或者把这个大组件拆解成小组件。
函数也是一样的,如果单个函数或方法中的代码行数太多,考虑拆开它。
不过最难的地方是封装粒度确认的问题,就是特定场景下如果封装组件,这个是永久的话题。
你需要redux吗,你需要axios吗,你需要moment.js吗,你需要decimal.js吗,有时候真的没必要。
这点其实在开发中很常见,比如状态管理,我们现在用的是recoil,hook形式的库,非常贴近我们的开发方式,有的项目直接不用状态管理库了。
有些js实现的,我们用css也是可以实现的,用js其实也没必要。
setState
时传入回调函数,所以没必要把 state
作为一个依赖项你不用把 setState
和 dispatch
放在 useEffect
和 useCallback
这些 hook 的依赖数组中。ESLint 也不会给你提示,因为 React 已经确保了它们不会出错。
❌ 不太好
const decrement = useCallback(() => setCount(count - 1), [setCount, count])
const decrement = useCallback(() => setCount(count - 1), [count])
✅ 推荐
const decrement = useCallback(() => setCount(count => (count - 1)), [])
useMemo
或 useCallback
没有任何依赖,那你可能用错了如果usememo和usecallback没有依赖,那就直接用常规的变量和函数吧
❌ 不太好
const MyComponent = () => {
const functionToCall = useCallback(x: string => `Hello ${x}!`,[])
const iAmAConstant = useMemo(() => { return {x: 5, y: 2} }, [])
/* 接下来可能会用到 functionToCall 和 iAmAConstant */
}
✅ 推荐
const I_AM_A_CONSTANT = { x: 5, y: 2 }
const functionToCall = (x: string) => `Hello ${x}!`
const MyComponent = () => {
/* 接下来可能会用到 functionToCall 和 I_AM_A_CONSTANT */
}
它不仅看起来更清晰,而且你只需要 import 一次,而不是两次。
❌ 不太好
// 你每次需要 import 两个变量
import { useContext } from 'react';
import { SomethingContext } from 'some-context-package';
function App() {
const something = useContext(SomethingContext); // 看起来 ok,但可以更好
// ...
}
✅ 推荐
// 在另一个文件中,定义这个 hook
function useSomething() {
const context = useContext(SomethingContext);
if (context === undefined) {
throw new Error('useSomething must be used within a SomethingProvider');
}
return context;
}
// 你只需要 import 一次
import { useSomething } from 'some-context-package';
function App() {
const something = useSomething(); // 看起来会更清晰
// ...
}
一般的
const { data } = this.state;
this.setState({ data: {...data, key: 1 } });
其实可以通过下面的方式
this.setState(({ data }) => ({ data: {...data, key: 1 } }));
this.setState((state, props) => {
return { counter: state.counter + props.step };
});
const Demo = ({ prop1, prop2, prop3, ...restProps }) => (
<div>
xxxx
{ restProps.something }
</div>
)
// 父组件使用Demo
<Demo
prop1={xxx}
prop2={xxx}
something={xxx}
/>
const { data, type, something } = this.state;
<Demo
data={data}
type={type}
something={something}
/>
可以换成下面的方式
const { data, type, something } = this.state;
<Demo
{...{ data, id, something }}
/>
创建弹层的三种方式:
// 弹层
const Dialog = () => <div>弹层</div>
// 某组件
render() {
return (
this.state.showDialog && <Dialog />
)
}
2.通过Portals创建通道,在根节点外部挂载组件-但还是需要每次引入并且在render里面调用
// 弹层
class Dialog extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
modalRoot.appendChild(this.el);
}
componentWillUnmount() {
modalRoot.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children || <div>xxxx</div>,
this.el,
);
}
}
// 某组件
render() {
return (
this.state.showDialog && <Dialog />
)
}
3.推荐使用ReactDom.render创建弹层-挂载根节点外层,使用也更方便
// demo
let dialog;
class Dialog {
show(children) { // 显示
this.div = document.createElement('div');
document.body.appendChild(this.div);
ReactDom.render(children || <div>xxxx</div>, this.div);
}
destroy() { // 销毁
ReactDom.unmountComponentAtNode(this.div);
this.div.parentNode.removeChild(this.div);
}
}
export default {
show: function(children) {
dialog = new Dialog();
dialog.show(children);
},
hide: xxxxx
};
// 某组件
import Dialog from 'xxx';
alert = () => {
Dialog.show(xxxx);
}
render() {
return (
<button onClick={this.alert}>点击弹层</button>
)
}
参考:
[React Bits](https://hateonion.github.io/react-bits-CN/)
[一份 2.5k star 的《React 开发**纲领》](https://juejin.cn/post/7076244324614144014#heading-8)
[React 开发必须知道的 34 个技巧【近1W字】](https://juejin.cn/post/6844903993278201870#heading-45)
「React进阶」 React全部api解读+基础实践大全(夯实基础2万字总结)
21个让React 开发更高效更有趣的工具
数组解构是基于symbol.iterator的,它会调用迭代器,运行返回新的数组,如果没有实现迭代器方法,就会报错。
对象解构不会调用迭代器,直接运行结果返回对象
解构”分为数组解构和对象解构,虽然都使用三个点构成的扩展运算符,但它们的语义是不同的,仔细看就会发现它们的上下文也是不同的。
const obj = {...obj}
const array = [...array]
下面的写法会报错
const obj = { name: 'James' };
// ⛔️ Error: Type Object must have a '[Symbol.iterator]()'
// method that returns an iterator.ts(2488)
const result = [...obj];
应该改成
const obj = { name: 'James' };
const result = [...[obj]];
console.log(result); // 👉️ [{name: 'James'}]
assets-manifest.json经常会在create-react-app这个脚手架的打包文件上看到,由webpack-manifest-plugin这个webpack插件产生。assets-manifest.json其实只是源文件和加哈希后文件的一个对比表,仅此而已。它不会对应用的运行产生任何影响,浏览器也不会去请求它。
另外还有runtime文件,这个主要是用来解析依赖关系等的。
需求:后端返回了一组图片,图片的宽度固定,高度不固定。前端要求图片展示为正方形,图片不能变形且自适应,如果图片高了则裁剪掉。
<div>
<div class="img-wrap">
<img src="">
</div>
</div>
.img-wrap {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%;
overflow: hidden;
}
.img-wrap img {
position: absolute;
width: 100%;
//height: 100%;
}
原理解析:img-wrap继承父元素的宽度,为了保证img-wrap容器的高度等于宽度,通过padding-bottom撑开高度,接下来图片只设置宽度让它等于父元素的宽度,图片的高度会自适应。父元素设置overflow:hidden,这样设置以后图片即使过高也能保证不变形,只是看起来像裁剪成了正方形。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.