ie9中使用flex布局

ps:用惯了flex布局 项目要兼容到ie9怎么办

先别急,先看一张flex布局在浏览器兼容性

ie9中使用flex布局_第1张图片

明显ie9不支持flex 那有没有办法让ie9支持flex呢。我的想法就是去用js控制div的位置 

如何去控制每个div的位置呢 

1、使用子绝父相 (子类用absolute 父类用relative)

       优点: IE6+都支持

       缺点:可是这样会打乱原有的布局、需要让每个子类去累加父类的相对位移、计算工作量大、几乎要去对每个element 计算

2、使用transform 的translate属性

       好的地方:相对原有位置移动、一般transform属性用的也比较少、不影响布局、

       缺点:只支持ie9+

权衡利弊后、一般现在都最低支持ie9、所以决定用方案2

 

好了现在控制位置的方案定下来了、可是在ie9中如何去读取不支持的display:flex呢

如果去读取element.currentstyle['display'] 得到值是block 

好消息是在ie中可以读取浏览器不认识的自定义属性 所以如果这么写是支持的即 -js-display:flex;

通过使用element.currentstyle['-js-display']就可读取到这个flex属性那么我们约定每次在写样式时都加上-js-display

当然也可以通过工具自动去加上这个兼容的写法

我们把实现思路写个伪代码

//读取dom中所有是flex的div样式

//根据每个flex样式去设置该div的位置

读取dom中所有是flex的div样式

/**
 * 查询所有flexbox
 */
export default function readAll(element) {

    // whether the element has a display flex style
    let isDisplayFlex = isFlexBox(element);
    let _ele = {
        element,
        classList:[],
        style:'',
        offsetLeft:0,
        offsetTop:0,
        computedStyle: {},
        tag: element.localName,
        children: []
    };
    // children of the element
    let index = -1;
    let childNode;

    if (isDisplayFlex) {
        element instanceof Element&&resetStyle(element);
        let alignSelf = 'stretch';
        if (isFlexBox(element.parentNode)) {
            const _props = getStyle(element.parentNode);
            alignSelf = _props['align-items'] || getDefaultProp('alignItems')
        }
        const props = getStyle(element);
        _ele = {
            element,
            isFlex:true,
            isNativeInline:judgeIsNativeInline(element),
            tag: element.localName,
            classList: getClassList(element),
            style:element.getAttribute('style')||'',
            offsetLeft:getOffset(element).left,
            offsetTop:getOffset(element).top,
            computedStyle:props,
            children: [],
            props: {
                flexDirection:getDefaultStyle(props,'flex-direction','flexDirection')|| getDefaultProp('flexDirection', props) || getDefaultProp('flexDirection'),
                flexWrap: getDefaultStyle(props,'flex-wrap','flexWrap') || getDefaultProp('flexWrap', props) || getDefaultProp('flexWrap'), //默认不换行
                alignItems: getDefaultStyle(props,'align-items','alignItems') || getDefaultProp('alignItems'),
                alignSelf: getDefaultStyle(props,'align-self')|| alignSelf,
                alignContent: getDefaultStyle(props,'align-content','alignContent') || getDefaultProp('alignContent'),
                justifyContent:getDefaultStyle(props,'justify-content','justifyContent') || getDefaultProp('justifyContent'), //默认左对齐
                order: getDefaultStyle(props,'order','order') || getDefaultProp('order'),
                flexShrink: getDefaultStyle(props,'flex-shrink','flexShrink')|| getDefaultProp('flexShrink', props) || getDefaultProp('flexShrink'),
                flexGrow:getDefaultStyle(props,'flex-grow','flexGrow') || getDefaultProp('flexGrow', props) || getDefaultProp('flexGrow')
            }
        };

        dealInlineFlex(element)
    }
    // for each child node of the element
    while (childNode = element.childNodes[++index]) {
        // whether the child is an element
        let isElement = childNode instanceof Element;
        if (isElement) {
            // push the child details to children
            let childDetails = readAll(childNode);
            if(isDisplayFlex){
                element instanceof Element&&resetStyle(element);
                //如果父类为flex且自己不是flex的时候
                if(!isFlexBox(childNode)){
                    const _style=getStyle(childNode);
                    childDetails.computedStyle=_style;
                    childDetails.style=childNode.getAttribute('style')||'';
                    childDetails.isNativeInline=judgeIsNativeInline(childNode);
                    childDetails.classList=getClassList(childNode);
                    childDetails.offsetLeft=getOffset(childNode).left;
                    childDetails.offsetTop=getOffset(childNode).top;
                    childDetails.props={
                        alignSelf: getDefaultStyle(_style,'align-self')||_ele.props.alignItems,
                        order: getDefaultStyle(_style,'order','order') || getDefaultProp('order'),
                        flexShrink: getDefaultStyle(_style,'flex-shrink','flexShrink')|| getDefaultProp('flexShrink', _style) || getDefaultProp('flexShrink'),
                        flexGrow:getDefaultStyle(_style,'flex-grow','flexGrow') || getDefaultProp('flexGrow', _style) || getDefaultProp('flexGrow')
                    }
                }
            }else{
                childDetails.offsetLeft=getOffset(childNode).left;
                childDetails.offsetTop=getOffset(childNode).top;
            }

            _ele.children.push(childDetails);
        }
    }

    return _ele;
}

 

设置每个flexbox的位置

/**
 * 循环设置位置
 * @param flexBox
 */
const render = (flexBox) => {
    flexBox.forEach(item => {
        //说明是flexBox
        if (item.isFlex) {
            new Flex(item);//设置每个flexBox的位置
        } else {
            render(item.children)
        }
    })

Flex类的一些实现细节

const remakePos = _children.map((item,index) => {
            const obj = item.element.getBoundingClientRect();
            const nativeStyle=item.style;
            const style = item.computedStyle;
            //console.log(style.width,obj.width)

            //排除掉fixed等影响布局的
            const isFixed = (style.position === 'absolute' || style.position === 'fixed');
            if (isFixed) {
                return {
                    isFixed,
                    props: {},
                    borderLeftWidth: 0,
                    borderRightWidth: 0,
                    marginLeft: 0,
                    marginRight: 0,
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0,
                }
            }
            let width =obj.width + parseInt(style.marginLeft) + parseInt(style.marginRight) + (item.isNativeInline?0:(parseInt(style.borderLeftWidth)+parseInt(style.borderRightWidth))) ;
            let height =obj.height + parseInt(style.marginTop) + parseInt(style.marginBottom) + (item.isNativeInline?0:(parseInt(style.borderTopWidth)+parseInt(style.borderBottomWidth)));
            let _x= - (item.offsetLeft - parseInt(style.marginLeft) - parseInt(computedStyle.borderLeftWidth)-parseInt(computedStyle.paddingLeft) - left);
            let _y= - (item.offsetTop - parseInt(style.marginTop) - parseInt(computedStyle.borderLeftWidth) -parseInt(computedStyle.paddingTop)- top);

            return {
                element: item.element,
                computedStyle:item.computedStyle,
                style:nativeStyle,
                isNativeInline:item.isNativeInline,
                isFixed,
                props: item.props,
                borderLeftWidth: parseInt(style.borderLeftWidth),
                borderRightWidth: parseInt(style.borderRightWidth),
                marginLeft: parseInt(style.marginLeft),
                marginRight: parseInt(style.marginRight),
                paddingLeft: parseInt(style.paddingLeft),
                paddingRight: parseInt(style.paddingRight),
                height,
                width,
                x: _x,
                y: _y,
            }
        }).filter((item) => !item.isFixed);
        //创建流动布局
        const flowBox = this.createFlowBox(remakePos);

        this.height = this.computedStyle.height ? this.height : flowBox.reduce((al, b) => {
            if (flexDirection.includes(FLEX_DIRECTION.COLUMN)) {
                return al + b.lineArrayWidth
            } else {
                return al + b.max
            }
        }, 0);
        //console.log('flowbox',flowBox)
        //开始布局
        const array = this.startLayout(flowBox);

 

npm地址:https://www.npmjs.com/package/flex-native

githup地址:https://github.com/robertpanvip/flex-native

欢迎吐槽

 

 

 

 

 

 

你可能感兴趣的:(前端,浏览器兼容,flex布局,css3,flex,javascript,html5)