寫在前面:
剛學習完慕課網里的一個幻燈片案例,自己加了剛學的react,兩者結合。首先讓大家看看效果 點擊此處
你可以先用純js實現上面的效果:我的github上的 JS代碼 或者 觀看慕課提供的課程。再趁熱打鐵加上react
React分析
JS實現
對於js來說,下面按鈕一點擊,就能根據當前的索引為按鈕和圖片綁定對應好的樣式:取到對應的DOM元素,加上定義好的樣式名,就能實現綁定效果。
React實現
但對於React來說,組件化開發的思想,可不是取得DOM元素就了事,因為React設計的初衷就是為了擺脫DOM。
那對於這個Demo,如何實現點擊按鈕,上面的圖片對應着變化呢?
這個Demo拆成兩個組件,一個圖片組件,一個按鈕。兩個組件共用一個屬性庫,這就解決問題了。只要屬性庫的值變化,兩個組件就都跟着變化
因為這里只有一個狀態,所以只要設置一個屬性state.current,但要是應用復雜建議使用數組包含起來。
首先看一下目錄結構
//---css 樣式文件 //---data //----imgDatas.json 存放圖片信息json文件 //---imgs 圖片存放 //---App.jsx //---index.html //---main.js //---package.json //---webpack.config.js
接下來定義一下webpack.config.js
var OpenBrowserPlugin = require('open-browser-webpack-plugin'); //自動打開瀏覽器 var config={ entry:'./main.js', //入口文件 output:{ path:'./', //輸出路徑 filename:'index.js' //輸出文件 }, plugins: [ new OpenBrowserPlugin({ //自動打開瀏覽器 url: 'http://localhost:8080' }) ], module:{ loaders:[{ test:/\.jsx?$/, //正則匹配 js 文件變化 exclude:/node_modules/, loader:'babel', query:{ presets:['es2015','react'] //將es6與react變成現代瀏覽器能看懂的語言 } },{ test:'/\.(png|jpg|woff|woff2)$/', loader:'url-loader?limit=8192' //自動將低於8192bit的圖片變成base64 },{ test:/\.json$/, loader:'json-loader' //加載json文件 }] } }; module.exports = config;
再看一下 package.json文件的內容
... "scripts": { "start": "webpack-dev-server" }, ... "dependencies": { "babel-core": "^6.10.4", "babel-loader": "^6.2.4", "babel-preset-es2015": "^6.9.0", "babel-preset-react": "^6.11.1", "json-loader": "^0.5.4", "open-browser-webpack-plugin": "0.0.2", "react": "^15.2.0", "react-dom": "^15.2.0" }
接下來看一下main.js 文件的內容
import React from 'react'; import ReactDOM from 'react-dom'; import Slider from './App.jsx'; //引入APP.jsx ReactDOM.render( <Slider/>, document.getElementById('example') );
最重要的內容是APP.jsx 接下來一起學習重頭戲
思路:
0.將數據引入,通過使用webpack的 json.loader,將json 格式的值讀取,方便后續拿到數據
var imgData = require('./data/imgDatas.json'); //將圖片名信息轉成圖片URL路徑信息 imgData.forEach((item, index)=>{ item.isRight = index % 2; //根據奇偶判斷 用於后面識別class="main-i_right" item.img = '/imgs/'+item.img; //jsoan數據加上相對路徑 });
1.拆分按鈕 templateCtrl 和圖片templateMain 組件
return ( <div className="slider"> <div className="main"> {templateMain} </div> <div className="ctrl"> {templateCtrl} </div> </div> );
2.設置getInitialState current:0 這個是用於判斷當前顯示的值,將會與索引index相比較,相同則ture 添加 class="main-i_active"
//ES5 的React getInitialState : function(){ return{ current : 0 }; }, //ES6 的React constructor(){ super(); this.state = { current : 0 }; }
3.根據圖片數據foreach設置templateCtrl templateMain 的props數據,並初始化各自組件中間狀態值isCenter為false
let templateMain=[],templateCtrl=[]; imgData.forEach((value , index)=>{ var center = this.state.current == index; //這是核心,用於根據state.current 與 索引的值相比較 從而給每個組件的isCenter ture或false 加上對應的active templateMain.push( <TemplateMainI key={index} {...value} //這里面有 img isRight isCenter={center} /> ); templateCtrl.push( <TemplateCtrlI key={index} src={value.img} isCenter={center} arrange={this.rearrange.bind(this,index)} //通過點擊觸發rearrange,傳遞對應索引 設置state.current /> ); });
4.渲染templateCtrl templateMain組件
class TemplateMainI extends React.Component{ render () { const props = this.props, mainClassName = (props.isRight?'main-i main-i_right':'main-i')+ (props.isCenter?' main-i_active':''); return( <div className={mainClassName}> <div className="caption"> <h2>{props.h1}</h2> <h3>{props.h2}</h3> </div> <img src={props.img} alt=""/> </div> ) } } class TemplateCtrlI extends React.Component{ render() { const props = this.props; var ctrlClassName = 'ctrl-i'+ ( props.isCenter ?' ctrl-i_active':''); return( <a className={ctrlClassName} onClick={props.arrange}> <img src={props.src} alt=""/> </a> ) } }
5.主方法:rearrange(index) 將選中值的state.current 設置為那個索引
rearrange(index){ this.setState({ current : index }); }
6.為了讓一開始渲染就有畫面呈現,我們設置 componentDidMount 將第一個畫面設置為最初始
componentDidMount(){ this.rearrange(0); }
接下來對比es6下的React
1、導入文件使用 import React from 'react'
2、var TemplateMainI = React.createClass({}) 寫法變成定義一個類繼承React的組件 class TemplateMainI extends React.Component{}
3、State
getInitialState : function(){ return{ imgsArrangeArr : [] }; },
在構造器中繼承父類
es6語法
constructor(){ super(); this.state = { imgsArrangeArr : [] }; }
4、function XXX(){} 變成 es6 方法的寫法 XXX(){}
5、onClick 傳遞到父組件之后,父組件的方法arrange 需要bind this
this.rearrange.bind(this,index)
其中還有很多變化需要細細研究 可以參考這篇文章
具體代碼可以研究下我的github地址 Preview_silder,動手做一遍,收益良多。同時非常感謝樓下的博友幫我指出的錯誤。
如果你已經學過了上面的內容,可以繼續此項目的進階,增加Redux整理數據 React+Redux 實現幻燈片
轉載請注明出處!!!