基于CSS3 Transform的自适应响应式React封装组件以及对于Swiper.js的封装
这三个小的组件是笔者对常见的一些操作的React封装,性能不一定优化,只是为了方便使用,随手写的,不过如果有什么功能建议欢迎开Issue
Github系列Repos
ScalableComponent
借鉴了pageResponse这个移动端响应式插件
核心思想就是基于CSS3 Transform中的scale变换,根据屏幕尺寸与视觉设计稿的尺寸对比进行自动释放,以求达到较好的浏览效果,适合于懒人快速适配。
Usage
设置视口
源代码
/ * Created by apple on 16/6/30. */import React, {Component, PropTypes} from "react";export default class ScalableComponent extends Component { //设置属性值 static propTypes = { mode: PropTypes.oneOf(['auto', 'contain', 'cover']), //选择的模式 width: PropTypes.number, //视觉稿宽度 height: PropTypes.number, //视觉稿高度 origin: PropTypes.string,//缩放中心点 wrapperBackgroundColor: PropTypes.string//背景颜色 }; / * @function 构造函数 * @param props */ constructor(props) { super(props); let userAgent = navigator.userAgent; //判断是否为指定设备 this.wp = userAgent.match(/Windows Phone ([\d.]+)/); //判断是否为WindowsPhone this.android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/); //判断是否为Android //获取设备的宽高比 this.state = { deviceWidth: document.documentElement.clientWidth, deviceHeight: document.documentElement.clientHeight }; //根据模式判断页面缩放比例 this.mode = this.props.mode || "auto"; //缩放中心 this.origin = this.props.origin || "left top 0"; //传入的视觉稿 this.visualWidth = this.props.width || 320; this.visualHeight = this.props.height || 504; this.wrapperBackgroundColor = this.props.wrapperBackgroundColor || "black"; this._calcScaleRatio = this._calcScaleRatio.bind(this); this._updateDimensions = this._updateDimensions.bind(this); } / * @function 为了避免重绘,在ComponentWillMount之前 */ componentDidMount() { //监听页面尺寸变化 window.addEventListener("resize", this._updateDimensions); } componentWillUnmount() { //移除页面尺寸变化监听 window.removeEventListener("resize", this._updateDimensions); } / * @function 更新屏幕尺寸 * @private */ _updateDimensions() { this.setState({ deviceWidth: document.documentElement.clientWidth, deviceHeight: document.documentElement.clientHeight }); } / * @function 计算缩放参数 * @private */ _calcScaleRatio() { //默认缩放比例为1 let scaleRatio = 1; let deviceAspectRatio = this.state.deviceWidth / this.state.deviceHeight; //计算传入的视觉稿的比 let visualAspectRatio = this.visualWidth / this.visualHeight; //计算缩放比 if (this.mode === "contain") { //如果是包含模式,根据宽高中较大值进行缩放 scaleRatio = deviceAspectRatio > visualAspectRatio ? this.state.deviceHeight / this.visualHeight : this.state.deviceWidth / this.visualWidth; } else if (this.mode === "cover") { scaleRatio = deviceAspectRatio {/*直接将子元素放置在这里*/} {this.props.children} ) }}
Mode
Contain
Contain模式即保证页面完全包含在浏览器窗口中,在保证页面的宽高比情况下调整页面的宽度或者高度中的较大者,使得页面水平垂直居中,左右或上下可能出现空白。
Cover
Cover模式即使页面完全覆盖浏览器窗口,保持页面的宽高比,调整页面的宽度或高度(较小者),页面水平垂直居中,超出浏览器窗口左右或上下的内容会被隐藏
Auto
保持页面的宽高比,调整页面的宽度,使页面宽度完全包含在浏览器窗口中
Demo:Swiper封装
笔者一开始只是想对于Swiper.js做简单的封装,但是后来发现好像Swiper.js没有官方的isomorphic版本,最终为了方便还是选择封装一个同时加载外部脚本与样式的小组件。
ReactExternalLoader:外部脚本/组件加载封装组件
Usage
import React from "react";import {render} from "react-dom";import {ReactExternalLoader} from "../external_loader";render({alert("Loaded!");}}> HI This is Demo For Scalable, document.getElementById('root'));
源代码
/ * Created by apple on 16/7/1. */import React, {Component, PropTypes} from "react";//加载ES6 Promise Polyfillrequire('es6-promise').polyfill();//判断某个脚本是否已经被加载const promises = {};/ * @function 用于加载Script脚本 * @param src * @returns {*} */function loadScript(src) { //判断该脚本是否被加载过 if (promises[src]) { return promises[src] } //构造一个Promise对象 let promise = promises[src] = new Promise(resolve => { //创建一个script元素 var el = document.createElement('script'); var loaded = false; //设置加载完成的回调事件 el.onload = el.onreadystatechange = () => { //防止重复加载 if ((el.readyState && el.readyState !== 'complete' && el.readyState !== 'loaded') || loaded) { return false; } //加载完成后将该脚本的onload设置为null el.onload = el.onreadystatechange = null; loaded = true; resolve(); }; el.async = true; el.src = src; let head = document.getElementsByTagName('head')[0]; head.insertBefore(el, head.firstChild); }); return promise;}/ * @function 用于加载CSS文件 * @param src * @returns {*} */function loadCSS(src) { //判断该脚本是否被加载过 if (promises[src]) { return promises[src] } //构造一个Promise对象 let promise = promises[src] = new Promise(resolve => { //创建一个script元素 var el = document.createElement('link'); el.rel = "stylesheet"; el.href = src; el.media = "only x"; var loaded = false; //设置加载完成的回调事件 el.onload = el.onreadystatechange = () => { //防止重复加载 if ((el.readyState && el.readyState !== 'complete' && el.readyState !== 'loaded') || loaded) { return false; } //加载完成后将该脚本的onload设置为null el.onload = el.onreadystatechange = null; loaded = true; el.media = "all"; resolve(); }; //获取文档头元素 let head = document.getElementsByTagName('head')[0]; //插入刚才创建好的元素 head.insertBefore(el, head.firstChild); }); return promise;}export class ReactExternalLoader extends Component { //设置默认的Props static defaultProps = { //需要加载的外部资源地址 srcArray: ['javascript:void(0)'], //正在加载的指示 loadingIndicator: ( Loading ), //加载完成回调 onLoad: () => { } }; //设置需要载入的Props static propTypes = { srcArray: React.PropTypes.array, loadingIndicator: React.PropTypes.object, onLoad: React.PropTypes.func }; //全局状态 state = { done: false }; / * @function 组件加载完毕之前的回调 */ componentWillMount() { Promise.all( this.props.srcArray.map((src)=> { //判断是否为JS if (typeof src === "string" && src.indexOf(".js") > -1) { return loadScript(src); } else { return loadCSS(src); } }) ).then( ()=> { //设置加载完成 this.setState({ done: true }); //调用外部的完成回调 this.props.onLoad(); } ); } / * @function 渲染方法 * @returns {*} */ render() { //如果加载完成 if (this.state.done) { //返回实际的子组件 return this.props.children } else { //返回加载指示 return this.props.loadingIndicator; } }}
Swiper封装与使用
Usage
/ * Created by apple on 16/7/4. */import React from "react";import {render} from "react-dom";import ScalableComponent from "../scalable";import {SwiperContainer, SwiperSlide} from "../../scroll/slider/swiper";render( HI Slide1 This is Demo For Scalable HI Slide2 This is Demo For Scalable , document.getElementById('root'));
最终效果:
关键字:react.js, swiper.js
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!