首页
统计
墙纸
留言
Search
1
PVE8优化
19 阅读
2
jenkins根据分支、文件夹打包
13 阅读
3
mysql创建数据库
12 阅读
4
vue-cli注册全局方法
7 阅读
5
开心的加班
7 阅读
web前端
Vue
CSS
javascript
React
那些年爬过过的坑
ES6
TypeScrippt
ES7
javascript图灵 - 总结
Node
面试总结
React-Native
Web优化
基础
AngularJS
拍摄
Flutter
Dart
Docker
Linux
mysql
PVE
登录
/
注册
Search
标签搜索
vue+elementui
Cicaba
累计撰写
146
篇文章
累计收到
13
条评论
首页
栏目
web前端
Vue
CSS
javascript
React
那些年爬过过的坑
ES6
TypeScrippt
ES7
javascript图灵 - 总结
Node
面试总结
React-Native
Web优化
基础
AngularJS
拍摄
Flutter
Dart
Docker
Linux
mysql
PVE
页面
统计
墙纸
留言
搜索到
107
篇与
的结果
2018-07-17
Blob对象
blob对象介绍一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式 blob对象本质上是js中的一个对象,里面可以储存大量的二进制编码格式的数据。创建blob对象创建blob对象本质上和创建一个其他对象的方式是一样的,都是使用Blob() 的构造函数来进行创建。 构造函数接受两个参数:第一个参数为一个数据序列,可以是任意格式的值。第二个参数是一个包含两个属性的对象{ type: MIME的类型, endings: 决定第一个参数的数据格式,可以取值为 "transparent" 或者 "native"(transparent的话不变,是默认值,native 的话按操作系统转换) 。 }Blob()构造函数允许使用其他对象创建一个Blob对象,比如用字符串构建一个blobvar debug = {hello: "world"}; var blob = new Blob([JSON.stringify(debug, null, 2)], {type : 'application/json'});既然是对象,那么blob也拥有自己的属性以及方法属性Blob.isClosed (只读)布尔值,指示 Blob.close() 是否在该对象上调用过。 关闭的 blob 对象不可读。Blob.size (只读)Blob 对象中所包含数据的大小(字节)。Blob.type (只读)一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。方法Blob.close()关闭 Blob 对象,以便能释放底层资源。Blob.slice([start[, end[, contentType]]])返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。其实就是对这个blob中的数据进行切割,我们在对文件进行分片上传的时候需要使用到这个方法。看到上面这些方法和属性,使用过HTML5提供的File接口的应该都很熟悉,这些属性和方法在File接口中也都有。 其实File接口就是基于Blob,继承blob功能并将其扩展为支持用户系统上的文件,也就是说:File接口中的Flie对象就是继承与Blob对象。blob对象的使用上面说了很多关于Blob对象的一些概念性的东西,下面我们来看看实际用途。分片上传首先说说分片上传,我们在进行文件上传的时候,因为服务器的限制,会限制每一次上传到服务器的文件大小不会很大,这个时候我们就需要把一个需要上传的文件进行切割,然后分别进行上传到服务器。假如需要做到这一步,我们需要解决两个问题:怎么切割?怎么得知当前传输的进度?首先怎么切割的问题上面已经有过说明,因为File文件对象是继承与Blob对象的,因此File文件对象也拥有slice这个方法,我们可以使用这个方法将任何一个File文件进行切割。代码如下:var BYTES_PER_CHUNK = 1024 * 1024; // 每个文件切片大小定为1MB . var blob = document.getElementById("file").files[0]; var slices = Math.ceil(blob.size / BYTES_PER_CHUNK); var blobs = []; slices.forEach(function(item, index) { blobs.push(blob.slice(index,index + 1)); });通过上面的方法。我们就得到了一个切割之后的File对象组成的数组blobs;接下来要做的时候就是讲这些文件分别上传到服务器。在HTTP1.1以上的协议中,有Transfer-Encoding这个编码协议,用以和服务器通信,来得知当前分片传递的文件进程。这样解决了这两个问题,我们不仅可以对文件进行分片上传,并且能够得到文件上传的进度。粘贴图片blob还有一个应用场景,就是获取剪切板上的数据来进行粘贴的操作。例如通过QQ截图后,需要在网页上进行粘贴操作。粘贴图片我们需要解决下面几个问题监听用户的粘贴操作获取到剪切板上的数据将获取到的数据渲染到网页中首先我们可以通过paste事件来监听用户的粘贴操作:document.addEventListener('paste', function (e) { console.info(e); });然后通过事件对象中的clipboardData 对象来获取图片的文件数据。clipboardData对象介绍介绍一下 clipboardData 对象,它实际上是一个 DataTransfer 类型的对象, DataTransfer 是拖动产生的一个对象,但实际上粘贴事件也是它。clipboardData 的属性介绍属性 类型 说明dropEffect String 默认是 noneeffectAllowed String 默认是 uninitializedfiles FileList 粘贴操作为空Listitems DataTransferItemList 剪切板中的各项数据types Array 剪切板中的数据类型 该属性在Safari下比较混乱items 介绍items 是一个 DataTransferItemList 对象,自然里面都是 DataTransferItem 类型的数据了。属性items 的 DataTransferItem 有两个属性 kind 和 type属性 说明kind 一般为 string 或者 filetype 具体的数据类型,例如具体是哪种类型字符串或者哪种类型的文件,即 MIME-Type方法方法 参数 说明getAsFile 空 如果 kind 是 file ,可以用该方法获取到文件getAsString function(str) 如果 kind 是 string ,可以用该方法获取到字符串str在原型上还有一些其他方法,不过在处理剪切板操作的时候一般用不到了。type 介绍一般 types 中常见的值有 text/plain 、 text/html 、 Files 。值 说明text/plain 普通字符串text/html 带有样式的htmlFiles 文件(例如剪切板中的数据)有了上面这些方法,我们可以解决第二个问题即获取到剪切板上的数据。document.addEventListener('paste', function (e) { console.info(e); var cbd = e.clipboardData; for(var i = 0; i < cbd.items.length; i++) { var item = cbd.items[i]; console.info(item); if(item.kind == "file"){ var blob = item.getAsFile(); if (blob.size === 0) { return; } console.info(blob); } } });最后我们需要将获取到的数据渲染到网页上。其实这个本质上就是一个类似于上传图片本地浏览的问题。我们可以直接通过HTML5的File接口将获取到的文件上传到服务器然后通过讲服务器返回的url地址来对图片进行渲染。也可以使用fileRender对象来进行图片本地浏览。fileRender对象简介从Blob中读取内容的唯一方法是使用 FileReader。FileReader接口有4个方法,其中3个用来读取文件,另一个用来中断读取。无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。方法名 参数 描述readAsBinaryString file 将文件读取为二进制编码readAsText file,[encoding] 将文件读取为文本readAsDataURL file 将文件读取为DataURLabort (none) 终端读取操作FileReader 接口包含了一套完整的事件模型,用于捕获读取文件时的状态。事件 描述onabort 中断onerror 出错onloadstart 开始onprogress 正在读取onload 成功读取onloadend 读取完成,无论成功失败通过上面的方法以及事件,我们可以发现,通过readAsDataURL方法及onload事件就可以拿到一个可本地浏览图片的DataURL。最终代码如下:document.addEventListener('paste', function (e) { console.info(e); var cbd = e.clipboardData; var fr = new FileReader(); var html = ''; for(var i = 0; i < cbd.items.length; i++) { var item = cbd.items[i]; console.info(item); if(item.kind == "file"){ var blob = item.getAsFile(); if (blob.size === 0) { return; } console.info(blob); fr.readAsDataURL(blob); fr.on<x>load=function(e){ var result=document.getElementById("result"); //显示文件 result.innerHTML='<img src="' + this.result +'" alt="" />'; } } } });原文
2018年07月17日
1 阅读
0 评论
0 点赞
2018-07-16
js图片压缩
function canvasDataURL(path, obj, callback) { var img = new Image(); img.src = path; img.onload = function () { var that = this; // 默认按比例压缩 let w = that.width, h = that.height, scale = w / h; w = obj.width || w; h = obj.height || (w / scale); let quality = 0.7; // 默认图片质量为0.7 //生成canvas let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); // 创建属性节点 let anw = document.createAttribute("width"); anw.nodeValue = w; let anh = document.createAttribute("height"); anh.nodeValue = h; canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); ctx.drawImage(that, 0, 0, w, h); // 图像质量 if (obj.quality && obj.quality <= 1 && obj.quality > 0) { quality = obj.quality; } // quality值越小,所绘制出的图像越模糊 let base64 = canvas.toDataURL('image/jpeg', quality); // 回调函数返回base64的值 callback(base64); }; }// 三个参数// file:一个是文件(类型是图片格式),// config:一个是文件压缩的后宽度,宽度越小,字节越小{width,height,quality}// callback:一个是容器或者回调函数base64转Blob对象 /** * 将以base64的图片url数据转换为Blob * @param urlData * 用url方式表示的base64图片数据 */ function convertBase64UrlToBlob(urlData) { var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }
2018年07月16日
1 阅读
0 评论
0 点赞
2018-07-13
redux-persist数据持久化
import { createStore } from 'redux'; import { persistReducer } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; import reducer from './reducer'; let persistedReducer = persistReducer({ key: 'auto', storage }, reducer); let store = createStore(persistedReducer); export default store;persistReducer(config, reducer)argumentsconfig objectrequired config: key, storagenotable other config: whitelist, blacklist, version, stateReconciler, debugreducer functionany reducer will work, typically this would be the top level reducer returned by combineReducersreturns an enhanced reducerimport React from "react"; import { HashRouter as Router, Route } from "react-router-dom"; import { PersistGate } from 'redux-persist/integration/react'; import { persistStore } from 'redux-persist'; import store from '../redux/store'; import { Provider } from 'react-redux'; import Index from '../redux/index'; import Login from '../redux/login'; let persistor = persistStore(store); export default ( <PersistGate loading={null} persistor={persistor}> <Router> <Provider store={store}> <div> <Route exact path='/' component={Index}></Route> <Route exact path='/login' component={Login}></Route> </div> </Provider> </Router> </PersistGate> );persistStore(store, [config, callback])argumentsstore redux store The store to be persisted.config object (typically null)callback function will be called after rehydration is finished.returns persistor objectpersistor objectthe persistor object is returned by persistStore with the following methods:.purge()purges state from disk and returns a promise.flush()immediately writes all pending state to disk and returns a promise.pause()pauses persistence.persist()resumes persistence官方文档
2018年07月13日
2 阅读
0 评论
0 点赞
2018-07-12
webpack按需加载
**require.ensurerequire.ensure() 是 webpack 特有的,已经被 import() 取代**require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String) //示例 const home = (location, callback) => { require.ensure([], require => { callback(null, require('./HomePage.jsx')) }, 'home') }给定 dependencies 参数,将其对应的文件拆分到一个单独的 bundle 中,此 bundle 会被异步加载。当使用 CommonJS 模块语法时,这是动态加载依赖的唯一方法。意味着,可以在模块执行时才运行代码,只有在满足某些条件时才加载依赖项。dependencies:字符串构成的数组,声明 callback 回调函数中所需的所有模块。callback:只要加载好全部依赖,webpack 就会执行此函数。require 函数的实现,作为参数传入此函数。当程序运行需要依赖时,可以使用 require() 来加载依赖。函数体可以使用此参数,来进一步执行 require() 模块。errorCallback:当 webpack 加载依赖失败时,会执行此函数。chunkName:由 require.ensure() 创建出的 chunk 的名字。通过将同一个 chunkName 传递给不同的 require.ensure() 调用,我们可以将它们的代码合并到一个单独的 chunk 中,从而只产生一个浏览器必须加载的 bundle。
2018年07月12日
2 阅读
0 评论
0 点赞
2018-07-11
js技巧
获取Element所在的索引, Array.prototype.indexOf.call(ElementCollection,targetElement)获取字符串中某个字符存在个数. String.split('targetString').length-1
2018年07月11日
3 阅读
0 评论
0 点赞
2018-06-28
js获取设置光标位置
window.getSelection() //返回一个 Selection 对象,表示用户选择的文本范围或光标的当前位置。 <!DOCTYPE html> <html> <head> <title>js24.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> <!-- 输入完毕之后光标自动移动到下一个框的方法 --> <script type="text/javascript"> function moveNext(object, index) { if (object.value.length == 4) { document.forms[0].elements[index + 1].focus(); } } function showResult() { var f = document.forms[0]; var result = ""; for (var i = 0; i < 4; i++) { result += f.elements[i].value; } alert(result); } </script> </head> <body onload="document.forms[0].elements[0].focus();"> <form> <input type="text" size=3 maxlength=4 onkeyup="moveNext(this,0);">- <input type="text" size=3 maxlength=4 onkeyup="moveNext(this,1);">- <input type="text" size=3 maxlength=4 onkeyup="moveNext(this,2);">- <input type="text" size=3 maxlength=4 onkeyup="moveNext(this,3);"><br> <input type="button" value="显示所有" onclick="showResult();"> </form> </body>
2018年06月28日
1 阅读
0 评论
0 点赞
2018-06-28
判断360浏览器
window.onload = function() { //application/vnd.chromium.remoting-viewer 可能为360特有 var is360 = _mime("type", "application/vnd.chromium.remoting-viewer"); if (isChrome() && is360) { alert("检测到是360浏览器"); } } //检测是否是谷歌内核(可排除360及谷歌以外的浏览器) function isChrome() { var ua = navigator.userAgent.toLowerCase(); return ua.indexOf("chrome") > 1; } //测试mime function _mime(option, value) { var mimeTypes = navigator.mimeTypes; for (var mt in mimeTypes) { if (mimeTypes[mt][option] == value) { return true; } } return false; }
2018年06月28日
1 阅读
0 评论
0 点赞
2018-05-06
React按需加载
1.Bundle.js Bundle组件会接受一个名为 load 的 props load值一是一个组件异步加载的方法 load -> function (cb) {...cb(/ 异步加载的组件 /)},由bundle-loader封装 这个方法需要传入一个回调函数作为参数 回调函数会在在方法内异步接收加载完的组件import React from 'react'; class Bundle extends React.Component { constructor(props){ super(props); this.state = { // 默认为空 mod: null } } componentWillMount() { // 加载初始状态 this.load(this.props); } componentWillReceiveProps(nextProps) { if (nextProps.load !== this.props.load) { this.load(nextProps); } } load(props) { // 重置状态 this.setState({ mod: null }); // 传入组件的组件 props.load((mod) => { this.setState({ mod: mod.default ? mod.default : mod }); }); } render() { // 不为空,则渲染传入的子组件函数 return this.state.mod ? this.props.children(this.state.mod) : null; } } export default Bundle; 2.lazyLoad.js 这个包装函数接受两个值,一个为经过bundle-loader封装的组件,另一个是组件的属性import React from 'react'; import Bundle from './Bundle'; // 默认加载组件,可以直接返回 null const Loading = () => <div>Loading...</div>; /* 包装方法,第一次调用后会返回一个组件(函数式组件) 由于要将其作为路由下的组件,所以需要将 props 传入 <Bundle load={loadComponent}> {Comp => (Comp ? <Comp {...props} /> : <Loading />)} </Bundle> */ const lazyLoad = (loadComponent,props) => {//Bundle 包含的是一个函数子组件 由Bundle.js里的this.props.children(this.state.mod)渲染 return( <Bundle load={loadComponent}> {Comp => (Comp ? <Comp {...props} /> : <Loading />)} </Bundle> );} export default lazyLoad; 3.路由使用有两种使用方式,一种是webpack配置(见下面第四点),另一种是在组件内直接引用bundle-loader(下面代码没注释的就是)//import Home from './page/Home.bundle';//这种方式需要配置webpack的loader //import Detail from './page/Detail.bundle';//这种方式需要配置webpack的loader //-------------------------------------------------- import Detail from 'bundle-loader?lazy&name=home!./page/Detail.bundle'; import Home from 'bundle-loader?lazy&name=home!./page/Home.bundle'; <BrowserRouter> <div> <Route exact path="/" render={()=> <Redirect to="/home"/> // <Home dispatch={dispatch} getState={getState} questionList={value.question}></Home> }/> <Route path="/home" render={()=>{ return lazyLoad(Home, { dispatch:dispatch, getState:getState, questionList:value.question } ); }}/> <Route path="/detail" render={(props)=>{ return lazyLoad(Detail, { pid:props.location.id, questionList:value.question, dispatch:dispatch, answer:value.answer } ); }}/> </div> </BrowserRouter> 4.如果使用webpack配置注意这段代码要放在js的loader之前,不然可能会报错,这段配合下面这两句引用使用//import Home from './page/Home.bundle';//这种方式需要配置webpack的loader//import Detail from './page/Detail.bundle';//这种方式需要配置webpack的loader[html] view plain copy{ test: /\.bundle\.js$/, loader: 'bundle-loader', options: { lazy: true, name: '[name]' }
2018年05月06日
0 阅读
0 评论
0 点赞
2018-05-06
react-redux
Redux 是「React 全家桶」中极为重要的一员,它试图为 React 应用提供「可预测化的状态管理」机制。Redux 本身足够简单,除了 React,它还能够支持其他界面框架。所以如果要将 Redux 和 React 结合起来使用,就还需要一些额外的工具,其中最重要的莫过于 react-redux 了。react-redux 提供了两个重要的对象,Provider 和 connect,前者使 React 组件可被连接(connectable),后者把 React 组件和 Redux 的 store 真正连接起来。react-redux 的文档中,对 connect 的描述是一段晦涩难懂的英文,在初学 redux 的时候,我对着这段文档阅读了很久,都没有全部弄明白其中的意思(大概就是,单词我都认识,连起来啥意思就不明白了的感觉吧)。在使用了一段时间 redux 后,本文尝试再次回到这里,给这段文档(同时摘抄在附录中)一个靠谱的解读。预备知识首先回顾一下 redux 的基本用法。如果你还没有阅读过 redux 的文档,你一定要先去阅读一下。const reducer = (state = {count: 0}, action) => { switch (action.type){ case 'INCREASE': return {count: state.count + 1}; case 'DECREASE': return {count: state.count - 1}; default: return state; } } const actions = { increase: () => ({type: 'INCREASE'}), decrease: () => ({type: 'DECREASE'}) } const store = createStore(reducer); store.subscribe(() => console.log(store.getState()) ); store.dispatch(actions.increase()) // {count: 1} store.dispatch(actions.increase()) // {count: 2} store.dispatch(actions.increase()) // {count: 3}通过 reducer 创建一个 store,每当我们在 store 上 dispatch 一个 action,store 内的数据就会相应地发生变化。我们当然可以直接在 React 中使用 Redux:在最外层容器组件中初始化 store,然后将state 上的属性作为 props 层层传递下去。class App extends Component{ componentWillMount(){ store.subscribe((state)=>this.setState(state)) } render(){ return <Comp state={this.state} onIncrease={()=>store.dispatch(actions.increase())} onDecrease={()=>store.dispatch(actions.decrease())} /> } }但这并不是最佳的方式。最佳的方式是使用 react-redux 提供的 Provider 和 connect 方法。使用 react-redux首先在最外层容器中,把所有内容包裹在 Provider 组件中,将之前创建的 store 作为prop 传给 Provider。const App = () => { return ( <Provider store={store}> <Comp/> </Provider> ) };Provider 内的任何一个组件(比如这里的 Comp),如果需要使用 state 中的数据,就必须是「被 connect 过的」组件——使用 connect 方法对「你编写的组件(MyComp)」进行包装后的产物。class MyComp extends Component { // content... } const Comp = connect(...args)(MyComp);可见,connect 方法是重中之重。connect 详解究竟 connect 方法到底做了什么,我们来一探究竟。首先看下函数的签名:connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])connect() 接收四个参数,它们分别是 mapStateToProps,mapDispatchToProps,mergeProps和options。mapStateToProps(state, ownProps) : stateProps这个函数允许我们将 store 中的数据作为 props 绑定到组件上。const mapStateToProps = (state) => { return { count: state.count } }这个函数的第一个参数就是 Redux 的 store,我们从中摘取了 count 属性。因为返回了具有 count 属性的对象,所以 MyComp 会有名为 count 的 props 字段。class MyComp extends Component { render(){ return <div>计数:{this.props.count}次</div> } } const Comp = connect(...args)(MyComp);当然,你不必将 state 中的数据原封不动地传入组件,可以根据 state 中的数据,动态地输出组件需要的(最小)属性。const mapStateToProps = (state) => { return { greaterThanFive: state.count > 5 } }函数的第二个参数 ownProps,是 MyComp 自己的 props。有的时候,ownProps 也会对其产生影响。比如,当你在 store 中维护了一个用户列表,而你的组件 MyComp 只关心一个用户(通过 props 中的 userId 体现)。const mapStateToProps = (state, ownProps) => { // state 是 {userList: [{id: 0, name: '王二'}]} return { user: _.find(state.userList, {id: ownProps.userId}) } } class MyComp extends Component { static PropTypes = { userId: PropTypes.string.isRequired, user: PropTypes.object }; render(){ return <div>用户名:{this.props.user.name}</div> } } const Comp = connect(mapStateToProps)(MyComp);当 state 变化,或者 ownProps 变化的时候,mapStateToProps 都会被调用,计算出一个新的stateProps,(在与 ownProps merge 后)更新给 MyComp。这就是将 Redux store 中的数据连接到组件的基本方式。mapDispatchToProps(dispatch, ownProps): dispatchPropsconnect 的第二个参数是 mapDispatchToProps,它的功能是,将 action 作为 props 绑定到MyComp 上。const mapDispatchToProps = (dispatch, ownProps) => { return { increase: (...args) => dispatch(actions.increase(...args)), decrease: (...args) => dispatch(actions.decrease(...args)) } } class MyComp extends Component { render(){ const {count, increase, decrease} = this.props; return (<div> <div>计数:{this.props.count}次</div> <button onClick={increase}>增加</button> <button onClick={decrease}>减少</button> </div>) } } const Comp = connect(mapStateToProps, mapDispatchToProps)(MyComp);由于 mapDispatchToProps 方法返回了具有 increase 属性和 decrease 属性的对象,这两个属性也会成为 MyComp 的 props。如上所示,调用 actions.increase() 只能得到一个 action 对象 {type:'INCREASE'},要触发这个 action 必须在 store 上调用 dispatch 方法。diapatch 正是 mapDispatchToProps 的第一个参数。但是,为了不让 MyComp 组件感知到 dispatch 的存在,我们需要将 increase 和decrease 两个函数包装一下,使之成为直接可被调用的函数(即,调用该方法就会触发dispatch)。Redux 本身提供了 bindActionCreators 函数,来将 action 包装成直接可被调用的函数。import {bindActionCreators} from 'redux'; const mapDispatchToProps = (dispatch, ownProps) => { return bindActionCreators({ increase: action.increase, decrease: action.decrease }); }同样,当 ownProps 变化的时候,该函数也会被调用,生成一个新的 dispatchProps,(在与statePrope 和 ownProps merge 后)更新给 MyComp。注意,action 的变化不会引起上述过程,默认 action 在组件的生命周期中是固定的。[mergeProps(stateProps, dispatchProps, ownProps): props]之前说过,不管是 stateProps 还是 dispatchProps,都需要和 ownProps merge 之后才会被赋给 MyComp。connect 的第三个参数就是用来做这件事。通常情况下,你可以不传这个参数,connect 就会使用 Object.assign 替代该方法。其他最后还有一个 options 选项,比较简单,基本上也不大会用到(尤其是你遵循了其他的一些 React 的「最佳实践」的时候),本文就略过了。希望了解的同学可以直接看文档。注意:和react-router混用时不能把route, connect(mapStateToProps, mapDispatchToProps)(route).必须分发最高层主件原文
2018年05月06日
2 阅读
0 评论
0 点赞
2018-05-06
React-Router V4
react-router-dom:使用 HTML5 提供的 history API 来保持 UI 和 URL 的同步;:使用 URL 的 hash (例如:window.location.hash) 来保持 UI 和 URL 的同步;:能在内存保存你 “URL” 的历史纪录(并没有对地址栏读写);:从不会改变地址;Route主件path(string): 路由匹配路径。(没有path属性的Route 总是会 匹配);exact(bool):为true时,则要求路径与location.pathname必须完全匹配;strict(bool):true的时候,有结尾斜线的路径只能匹配有斜线的location.pathname;Route渲染方式:在地址匹配的时候React的组件才会被渲染,route props也会随着一起被渲染;:这种方式对于内联渲染和包装组件却不引起意料之外的重新挂载特别方便;:与render属性的工作方式基本一样,除了它是不管地址匹配与否都会被调用;Switch主件的独特之处是独它仅仅渲染一个路由。相反地,每一个包含匹配地址(location)的都会被渲染。思考下面的代码路由嵌套V4的嵌套,和V2V3相当不同V4必须在主件的内部嵌套route例子如下:import React, {Component} from 'react'; import {Route} from 'react-router-dom'; import lazyLoad from '../lazyLoad'; import Index from 'bundle-loader?lazy&name=home!./index'; export default class Login extends Component { render() { return ( <div>测试 <Route path={this.props.match.path + '/index'} render={() => { return lazyLoad(Index, { ...this.props }); }}></Route> </div> ); } }
2018年05月06日
5 阅读
0 评论
0 点赞
1
...
4
5
6
...
11