我正在构建一个用于管理营销目标网页的CMS系统。在“编辑登录页面”视图中,我希望能够为用户正在编辑的任何登录页面加载相关的样式表。我怎么能用React做这样的事情?
我的应用程序完全React,isomorphic,在Koa上运行。我对该页面的基本组件层次结构看起来像这样:
App.jsx (has `<head>` tag)
└── Layout.jsx (dictates page structure, sidebars, etc.)
└── EditLandingPage.jsx (shows the landing page in edit mode)
着陆页的数据(包括要加载的样式表的路径)在EditLandingPage
的{{1}}中异步提取。
如果您需要任何其他信息,请与我们联系。很想得到这个想法!
奖励:我还想在离开页面时卸载样式表,我认为我可以反过来ComponentDidMount
中的任何答案,对吗?
答案 0 :(得分:19)
只需使用react的状态更新您希望动态加载的样式表路径。
import * as React from 'react';
export default class MainPage extends React.Component{
constructor(props){
super(props);
this.state = {stylePath: 'style1.css'};
}
handleButtonClick(){
this.setState({stylePath: 'style2.css'});
}
render(){
return (
<div>
<link rel="stylesheet" type="text/css" href={this.state.stylePath} />
<button type="button" onClick={this.handleButtonClick.bind(this)}>Click to update stylesheet</button>
</div>
)
}
};
此外,我已将其实施为反应组件。您可以通过npm install react-dynamic-style-loader安装。
检查我的github存储库以检查:
https://github.com/burakhanalkan/react-dynamic-style-loader
答案 1 :(得分:6)
这是主要的混合体。首先,我们将定义一个帮助程序来管理样式表。
我们需要一个加载样式表的函数,并返回一个成功的承诺。样式表实际上很难检测到负载......
function loadStyleSheet(url){
var sheet = document.createElement('link');
sheet.rel = 'stylesheet';
sheet.href = url;
sheet.type = 'text/css';
document.head.appendChild(sheet);
var _timer;
// TODO: handle failure
return new Promise(function(resolve){
sheet.onload = resolve;
sheet.addEventListener('load', resolve);
sheet.onreadystatechange = function(){
if (sheet.readyState === 'loaded' || sheet.readyState === 'complete') {
resolve();
}
};
_timer = setInterval(function(){
try {
for (var i=0; i<document.styleSheets.length; i++) {
if (document.styleSheets[i].href === sheet.href) resolve();
} catch(e) { /* the stylesheet wasn't loaded */ }
}
}, 250);
})
.then(function(){ clearInterval(_timer); return link; });
}
好吧$#!@ ...我本来希望只是坚持一下,但是没有。这是未经测试的,所以如果有任何错误请更新它 - 它是从几篇博客文章中编译的。
其余的相当直接:
var mixin = {
componentWillMount: function(){
this._stylesheetPromises = [];
},
loadStyleSheet: function(name, url){
this._stylesheetPromises.push(loadStyleSheet(url))
.then(function(link){
var update = {};
update[name] = true;
this.setState(update);
}.bind(this));
},
componentWillUnmount: function(){
this._stylesheetPromises.forEach(function(p){
// we use the promises because unmount before the download finishes is possible
p.then(function(link){
// guard against it being otherwise removed
if (link.parentNode) link.parentNode.removeChild(link);
});
});
}
};
同样,未经测试,如果有任何问题请更新。
现在我们有了组件。
React.createClass({
getInitialState: function(){
return {foo: false};
},
componentDidMount: function(){
this.loadStyleSheet('foo', '/css/views/foo.css');
},
render: function(){
if (!this.state.foo) {
return <div />
}
// return conent that depends on styles
}
});
唯一剩下的待办事项是在尝试加载之前检查样式表是否已存在。希望这至少可以让你走上正确的道路。
答案 2 :(得分:6)
我认为Burakhan的答案是正确的,但是将<Link href = "" />
加载到body标签内部很奇怪。这就是为什么我认为应该将其修改为以下[我使用React钩子]:
import * as React from 'react';
export default MainPage = (props) => {
const [ stylePath, setStylePath ] = useState("style1.css");
const handleButtonClick = () => {
setStylePath({stylePath: 'style2.css'});
}
useEffect(() => {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = stylePath;
head.appendChild(link);
return () => { head.removeChild(link); }
}, [stylePath]);
return (
<div>
<button type="button" onClick={handleButtonClick}>
Click to update stylesheet
</button>
</div>
);
};
答案 3 :(得分:0)
这是我动态添加样式的方式:
var str = 'Hello Hello word world going Hello world';
var strToSearch = "Hello"; //search this in str
var strMatch = "";
function wordMatch(str, length) {
for (var h = length; h < str.length; h++) {
if (str[h] === ' ') {
strMatch = "";
console.log('white Space')
} else {
strMatch += str[h];
//
if (strMatch === strToSearch) {
var len2 = str.length - strMatch.length;
console.log(len2,"Matched...");
wordMatch(str, len2-1);
strMatch = "";
//return false;
}else{
console.log('cont.........................')
}
}
}
}
wordMatch(str, 0);
答案 4 :(得分:0)
除了为样式表创建元素外,您还可以尝试根据某些条件导入CSS。 ECMAScript提供了启用动态模块导入的建议,其工作方式如下:
if (condition) {
import('your css path here').then((condition) => {});
}
答案 5 :(得分:0)
我在渲染函数中使用 react-helmet....
{inject ?
<Helmet>
<link rel="stylesheet" href="css/style.css" />
</Helmet> : null}