betamee / reactblog Goto Github PK
View Code? Open in Web Editor NEWa blog system based on React+Node
a blog system based on React+Node
搞react server side rendering,有一万万买想到的大坑,就是CSS样式文件无法在服务器环境使用,因为初始加载服务端要通过react renderToString方法生成HTML发送到客户端,其中组件引入的CSS样式就会报错,无法识别。这个项目用的是CSS Module+CSS in JS(Material UI 用的是内联样式),查了很多,最终加两个钩子解决问题。
启动脚本:index.js
require('babel-polyfill');
//加载样式钩子,补足服务端渲染无法识别CSS文件的情况
require('css-modules-require-hook')({
extensions: ['.css'],
generateScopedName: '[name]__[local]-[hash:base64:8]'
});
// Image required hook
//引入asset-require-hook,来识别图片资源,对小于8K的图片转换成base64字符串,大于8k的图片转换成路径引用。
require('asset-require-hook')({
extensions: ['jpg', 'png', 'gif','webp'],
limit: 10000
});
//处理字体
require('asset-require-hook')({
extensions: ['ttf','woff','svg','eot','woff2'],
limit: 10000
});
//启动服务端脚本
require('./server/server');
原理我的理解应该是:启动服务器脚本之前钩子进行劫持,不让服务端进行渲染,只生成类名,导入HTML中。(这里如果又理解错误可以再讨论)
还有一个asset-require-hook
钩子是对图片和字体打包资源的一个劫持,跟CSS思路一致,这样的话整个同构应用就解决了热加载、CSS样式、状态调试等一系列问题,至于还有什么坑,等着做的过程中再去踩吧。
本来想通过设置div元素contenteditable=true来制作markdown编辑器的,textarea无法自适应,写多了有滚动条。但contenteditable方法也有缺陷,考虑到div元素没有onChange事件绑定,如何获取<div>hello</div>
中的文本节点呢?(这个文本是我需要的)我是设想在componentDidMount后,通过findDOMNode来获取真实节点:
componentDidMount() {
const {getTitleInput,getContentInput,editorState} = this.props;
const realDom = findDOMNode(this.refs.textarea);//找到真实节点
realDom.addEventListener('DOMSubtreeModified',e=>this.handleTextAreaChange(e));//监听DOM文本节点,获取文本数据
}
通过DOMSubtreeModified事件监听文本的变化抽取e.target.nodeValue(注意,不是e.target.value,与react不同,可以console看一下e对象)。问题是,当我在编辑的时候连续输入还好,一旦回车后,就会发生这样的事:
<div>hello
<div><br/></div>
</div>
产生了 <div><br/></div>
这样的结构,百思不得其解,这样我就无法抽取nodeValue了。
放弃了。。先用textare凑个数,以后再研究。
一个需求:比如新建文章,发送到服务器后,这时候页面应该有个跳转
PostAction.js
export const SendPostToServer = (title,content)=>{
//post by fetch
}
由于整个react组件的改变状态变化的权利都交给了redux,意味着所有必须在action层中完成跳转。
使用react-router-redux提供的api:
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { routerMiddleware, push } from 'react-router-redux'
// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
reducers,
applyMiddleware(middleware)
)
// Dispatch from anywhere like normal.
store.dispatch(push('/foo'))
所以我的代码部分是这样的:
export const SendPostToServer = (title,content)=>{
return (dispatch,getState)=>{
dispatch(RequestPosts());//先表明正在请求
return request.post(`/api/posts`,{title,content},{
headers:{
'Content-Type': 'application/json;charset=utf-8',
'Authorization':`${GetTokenFromStorage()}`
}
})
.then(res=>{
let resStatus=res.data;
if(!resStatus.success){
dispatch(ErrorHandle(resStatus.message));
dispatch(CreateOpenSnackbar());//开启snaker
}else{
dispatch(GetPostSended(resStatus.message));
dispatch(ChangePostsCounts(resStatus.counts));
dispatch(CreateOpenSnackbar());//开启snaker
dispatch(push(`/posts`)); //通过react-router-redux进行切换
}
})
.catch(err=>{
dispatch(ErrorHandle(err.message));
dispatch(CreateOpenSnackbar());//开启snaker
});
}
}
完美解决
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
参考:
Mongoose - 在 NodeJs 中优雅地建立 MongoDb 对象模型
Mongoose Populate 基本使用
Mongoose populate 预填充字段
Mongoose ref关联删除数据
在mongoose中填充外键
Mongoose 之 Population 使用
今天设计react-router中组件的时候踩了一个巨坑。
起因是这样的,我的AppRoutes.js是这样的:
<Route path="/" component={Layout}>
<IndexRoute component={IndexContainer} />
<Route path="/posts" component={PostsLayout}>
<IndexRoute component={Posts}/>
<Route path="/posts/:id" component={PostOne}/>
</Route>
</Route>
照理来说,'/'对应着:Layout->IndexContainer
,'/posts'对应着Layout->PostsLayout->Posts
, '/posts/123'为Layout->PostsLayout->PostOne
,但是输入'/'和'/posts'一切正常,'/posts/123'就会报Unexpected token <
的错。我以为是服务端渲染问题或者版本问题,降级了react router到2.8(原来3.0),还是不行,去StackOver上查很多,终于找到了问题!!!!!!!!!!!!
原来是script脚本加载问题,我的view模板中是这样的:
<script src='devClient.bundle.js'></script>
,看到没!!(好像没问题啊。。。x_x)
事实上,当我输入localhost:3000/posts/123
的时候,脚本加载方式为localhost:3000/posts/devClient.bundle.js
,
咦,这里肯定不对啊,哪来的posts路径?!
所以正确的写法是加上绝对路径<script src='/devClient.bundle.js'></script>
,万无一失,保平安啊。
以及贴上原帖供参考:
Unexpected token < error in react router component
又踩坑了。
发现了一个比较严重的问题,就是整个react应用页面切换的时候滚动条不会重置到最顶端。
比如有两个页面,第一个页面没滚动,进去第二个,滚到底,返回第一个页面也滚到底。这个应该是React-Router上的问题,React Router 不维护 scroll position。
所以有两个方法,一个是在组件更新的时候componentWillUpdate
期间调用window.scrollTo(0.0)
,问题是这个项目是server side rendering,服务端可没有window这个对象。此计不行。
查react-router issue,有一个方法是这样的:
<Router onUpdate={() => window.scrollTo(0, 0)} history={createBrowserHistory()}>
...
</Router>
但是这个还不是要在服务端运行吗?,不抱希望地试了试,结果可行!那就得出一个结论,组件初始渲染生成HTML,生命周期是到componentWillUpdate
(相关资料),所以window对象无法使用,但Router组件不参与渲染,所以加上一个更新函数可用。
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.