Решение проблемы совместимости iview в ie9 и выше

внешний интерфейс JavaScript Vue.js iView
Решение проблемы совместимости iview в ie9 и выше

Пришло время показать эту картинку:

Но т.е. несовместимо, если вы не хотите быть совместимым. Я буду плакать, если продолжу.

Пользуюсь iview больше года. В общем, iview привнес в мою работу большое удобство.

Основная претензия заключается в том, что документация недостаточно ясна.

Например, введение компонентов по требованию требует всего нескольких слов.После прочтения введения согласно документу консоль продолжает сообщать об ошибках.

Потом я перешел к следующему элементу, чтобы увидеть, что есть не один способ его внедрить, а некоторые нужно пройти через vue.prototype.xxx.

Также есть описание совместимости,

Когда вы так говорите, я думал, что ie9 может использовать полифиллы напрямую, но кто знает, что это вообще не сработает. Я поднял вопрос на github и сказал, что более низкая версия ie не поддерживается.

По моему опыту, серьезных изменений не требуется, а совместимость примерно ie10+, что также соответствует официальной документации element.

Я не знаю, делает ли это iview, чтобы привлечь больше людей в яму или что происходит, ведь большинство разработчиков сначала смотрят официальную документацию, вместо того, чтобы идти на github, чтобы найти проблему во время разработки.

Tucao возвращается в Tucao, iview в целом хорош. Поговорим о проблемах совместимости и решениях ie9+, с которыми я столкнулся в процессе использования iview.

Установить babel-полифилл

Internet Explorer не имеет встроенного объекта Promise. Мало того, почти все новые методы ES6 недоступны в IE, в этом случае вам понадобится babel Polyfill.

  1. первый

    npm install babel-polyfill --save
    
  2. Изменить webpack.base.conf.js

    перед фиксацией

    entry: {
        main: './src/main',
    },
    

    после модификации

    entry: {
        main: ["babel-polyfill","./src/main"],
    },
    

    Посмотрев несколько руководств в Интернете, после установки babel-polyfill и установки es6-prommise, я могу сказать только одно предложение: лишнее.

Совместимость с наборами данных

[Vue warn]: Error in directive transfer-dom inserted hook: "TypeError: 无法获取未定义或 null 引用的属性“transfer”"

Это вызвано тем, что ie10 и ниже не поддерживают набор данных, и трансфер-dom.js iview использует это свойство

Решение: добавьте следующий код в main.js

if (window.HTMLElement) {
    if (Object.getOwnPropertyNames(HTMLElement.prototype).indexOf('dataset') === -1) {
        Object.defineProperty(HTMLElement.prototype, 'dataset', {
            get: function () {
                var attributes = this.attributes; // 获取节点的所有属性
                var name = [];
                var value = []; // 定义两个数组保存属性名和属性值
                var obj = {}; // 定义一个空对象
                for (var i = 0; i < attributes.length; i++) { // 遍历节点的所有属性
                    if (attributes[i].nodeName.slice(0, 5) === 'data-') { // 如果属性名的前面5个字符符合"data-"
                        // 取出属性名的"data-"的后面的字符串放入name数组中
                        name.push(attributes[i].nodeName.slice(5));
                        // 取出对应的属性值放入value数组中
                        value.push(attributes[i].nodeValue);
                    }
                }
                for (var j = 0; j < name.length; j++) { // 遍历name和value数组
                    obj[name[j]] = value[j]; // 将属性名和属性值保存到obj中
                }
                return obj; // 返回对象
            },
        });
    }
}

Понизить версии зависимостей

Если вы столкнулись со следующей ошибкой:

错误1:“webpackJsonp”未定义

решение:

Измените версию webpack-dev-server 2.71 или ниже.

npm install --save-dev webpack-dev-server@2.7.1

Совместимость с requestAnimationFrame (ie9)

ie9 не поддерживает requestAnimationFrame.Если вы используете его и получаете ошибку, это не имеет значения, просто посмотрите вниз.

Решение: добавьте следующий код в main.js

// window.requestAnimationFrame多浏览器兼容问题补丁
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license

(function () {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
            window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function (callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function () { callback(currTime + timeToCall); },
                timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }

    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function (id) {
            clearTimeout(id);
        };
    }
}());

Совместимость с classList (ie9)

Сообщение об ошибке:无法获取未定义或 null 引用的属性“add”

无法获取未定义或 null 引用的属性“remove”

Если вы посмотрите на исходную карту и найдете classList().add или classList.remove() и т. д., это должно быть проблемой с classList.

Решение: добавьте следующий код в main.js

if (!('classList' in document.documentElement)) {
    Object.defineProperty(HTMLElement.prototype, 'classList', {
        get: function () {
            var self = this;
            function update(fn) {
                return function (value) {
                    var classes = self.className.split(/\s+/g);
                    var index = classes.indexOf(value);

                    fn(classes, index, value);
                    self.className = classes.join(' ');
                };
            }

            return {
                add: update(function (classes, index, value) {
                    if (!~index) classes.push(value);
                }),

                remove: update(function (classes, index) {
                    if (~index) classes.splice(index, 1);
                }),

                toggle: update(function (classes, index, value) {
                    if (~index) { classes.splice(index, 1); } else { classes.push(value); }
                }),

                contains: function (value) {
                    return !!~self.className.split(/\s+/g).indexOf(value);
                },

                item: function (i) {
                    return self.className.split(/\s+/g)[i] || null;
                },
            };
        },
    });
}

Избегайте использования location.href для переходов маршрутизации внутри проекта.

Для повышения производительности мы обычно используем ленивую загрузку маршрутизации. В одностраничном приложении каждый раз при открытии страницы загружается только соответствующий файл ресурсов.

Если вы перейдете на предыдущую страницу, обычно страница будет использовать кэшированный файл ресурсов и больше не будет загружаться, что эффективно повышает эффективность загрузки страницы.

Однако, если используется метод location.href, страница будет полностью обновлена, и все ресурсы страницы будут загружены повторно, что не позволяет эффективно использовать кеш.

Их можно просмотреть из сети в консоли Chrome.

Что еще более важно, если вы используете location.href напрямую, браузер IE может не обновить страницу при изменении URL-адреса!

Например, маршрут следующим образом:

127.0.0.1:8080/#/дом

127.0.0.1:8080/#/об

Текущая страница 127.0.0.1:8080/#/home,

Нажмите кнопку, чтобы прыгнуть

jump(){
    location.href = '/#/about'
}

Вы обнаружите, что URL-адрес адресной строки браузера изменился, а страница по-прежнему остается домашней! Поэтому вы должны использовать

jump(){
    let url = '/#/about';
    let path = url.split('#')[1];
    this.$router.push(path);
}

Теперь прыгать не проблема.

Конечно, если вам приходится где-то использовать location.href, например, у вас есть доступ к каким-то сторонним сервисам, которые вы не можете контролировать, есть решения: добавить следующий код в созданный или смонтированный жизненный цикл файла корневой экземпляр vue:

window.addEventListener('hashchange', () => {
    let currentPath = window.location.hash.slice(1);
    if (this.$route.fullPath !== currentPath) {
        this.$router.push(currentPath);
    }
}, false);

Прослушивая hashchange, как только обнаруживается, что URL-адрес текущей страницы отличается от URL-адреса адресной строки браузера, вызывается метод маршрутизации vue для перехода к URL-адресу адресной строки.

Этот метод также срабатывает, если целевая страница активна, но не действует.

использовать scrollTop

Если страница слишком длинная, мы добавим кнопку для прокрутки вверх

toTop(el){
    el.scrollTo(0, 0);
}

Кто знает, что т.е. на самом деле равнодушен! Попробовав некоторое время, я обнаружил, что браузер IE не поддерживает scrollTo.

Измените его на это:


toTop(el){
    if (el && el.scrollTo) {
        el.scrollTo(0, 0);
    } else {
        el.scrollTop = 0;
    }
}

т.е. также может прокручиваться вверх.

ie9 не поддерживает кросс-доменный cors

Это самый прискорбный момент.Хотя страница открывается в ie10+, в некоторых местах будет выдаваться ошибка, а ie9 вообще не покажет страницу, то есть страницу не отобразит!

Ошибка консоли: Отказано в доступе!

Кроме этого, другой информации нет.

Многократно проверяя документацию axios и vue, все они говорят, что поддерживается ie9.

Давно мучает меня эта проблема, конкретного сообщения об ошибке нет, и нет возможности запустить.

Проверяйте по очереди, это не будет проблемой аксиом.

После поиска выяснилось, что: ie8/9 не поддерживает междоменную схему cors, и заменен методом XDomainRequest ie

Не хочу больше изучать метод XDomainRequest. Напрямую используйте метод прокси-сервера, предоставляемый webpack-dev-server (при условии, что в фоновом режиме настроен междоменный доступ), который примерно выглядит следующим образом:

devServer: {
    port: 8080,
    proxy: {
        '/api': {
        target: 'http://xx.xx.cn/',
        pathRewrite: {'^/api' : ''},
        changeOrigin: true
        }
    }
}

Чтобы узнать больше, см. этоМеждоменный запрос ресурсов в IE8 и 9

Не используйте новую дату (гг-мм-дд) для форматирования даты

В браузере ie, если вы используете новую дату ('2018-09-12') напрямую, то есть будет отображаться недействительная дата. Чтобы обеспечить стабильную производительность во всех браузерах, вы должны использовать новую дату ('2018/09/12' ) таким образом.

Определить версию браузера

function IEVersion () {
	var userAgent = navigator.userAgent; // 取得浏览器的userAgent字符串
	var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1; // 判断是否IE<11浏览器
	var isEdge = userAgent.indexOf('Edge') > -1 && !isIE; // 判断是否IE的Edge浏览器
	var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
	if (isIE) {
		var reIE = new RegExp('MSIE (\\d+\\.\\d+);');
		reIE.test(userAgent);
		var fIEVersion = parseFloat(RegExp['$1']);
		if (fIEVersion === 7) {
			return 7;
		} else if (fIEVersion === 8) {
			return 8;
		} else if (fIEVersion === 9) {
			return 9;
		} else if (fIEVersion === 10) {
			return 10;
		} else {
			return 6;// IE版本<=7
		}
	} else if (isEdge) {
		return 'edge';// edge
	} else if (isIE11) {
		return 11; // IE11
	} else {
		return -1;// 不是ie浏览器
	}
};

Не используйте некоторые новые функции

Я использовал translateX() и обнаружил, что ie9 безразличен, так что давайте просто используем относительное позиционирование;

Линейный градиент linear-gradient() можно использовать, но IE не распознает его, поэтому сначала установите сплошной цвет фона или фона изображения, а затем установите линейный градиент, иначе фон IE нельзя будет установить.

Flex-макет — это круто, но не используйте его. Для того же эффекта хороша и раскладка стола.