Помните небольшую яму -- о window.open()

внешний интерфейс Ресурсы изображений поисковый движок Vue.js

Сегодня столкнулся с таким требованием в фоновом проекте компании: нажать кнопку, отправить запрос, а затем использовать запрошенныйdataсерединаurlОткрыть новое окно (перейти к другому фону). Вроде проблем быть не должно, и код скоро будет написан (проект vue, ниже псевдокод, в основном выражающий идею):

clickHandle() {
  api.get('xxx', params).then(response => {
    let data = response.data;
    if(data.code === 0 ) {
      let url = data.data.url || '';
      if (url) {
        window.open(url);
      }
    }
  });
}

После счастливого тестирования я обнаружил, что новое окно не появляется.После короткой паники я обнаружил, что браузер заблокировал открытие нового окна. . .

Поисковики говорят мне,Открытие новых окон, не вызванное поведением пользователя, может быть заблокировано некоторыми браузерами.(В Google Chrome оно отображается в виде значка уведомления в конце адресной строки, и, щелкнув уведомление, можно разрешить или продолжить блокировку). Поисковая система также заявила, что поведение пользователя можно имитировать, вручную запуская события dom, чтобы избежать перехвата браузером.

С учетом вышеизложенных идей я изменил псевдокод следующим образом:

clickHandle() {
  api.get('xxx', params).then(response => {
    let data = response.data;
    if(data.code === 0 ) {
      let url = data.data.url || '';
      if (url) {
        // window.open(url);
        // 在dom中添加a标签-注册点击事件打开新窗口-触发点击事件-从dom中移除a标签
        let a = document.createElement('a');
        a.id = 'temp';
        document.body.appendChild(a);
        a.addEventListener('click', function(){
          window.open(url);
        });
        a.click();
        document.body.removeChild(a);
      }
    }
  });
}

Отлично, снова успешно протестировано, однако браузер все еще заблокирован. . .

Улыбайся постепенно непристойно. Улыбка постепенно затвердевала. Осень.

Поисковик снова сказал мне,Пока он выполняется в асинхронном обратном вызовеwindow.open()будет заблокирован.

Хорошо, разберемся с идеями: на этот раз мы не в асинхронном коллбекеwindow.open(). Нажмите кнопку, чтобы сначала открыть новое окно, и сохраните ссылку на новое окно вdataвнутри. запрос на получениеurlПосле этого поставитьurlтакже сохранено вdataвнутри. тогда мыwatchодин разurl,urlЕсли есть значение, перенаправить ссылку на новое окно. Давайте помолимся, чтобы на этот раз ничего не случилось. Код изменен следующим образом:

export default {
  data() {
    return {
      url: '',
      newWin: null  // 新窗口的引用
    }
  },
  watch: {
    url(newVal, oldVal) {
      if(newVal && this.newWin) {
        this.newWin.location.href = newVal;
        // 重定向后把url和newWin重置
        this.url = '';
        this.newWin = null;
      }
    }
  },
  methods: {
    clickHandle() {
      let _this = this;
      // 先打开一个空的新窗口,再请求
      this.newWin = window.open();
      api.get('xxx', params).then(response => {
        let data = response.data;
        if(data.code === 0 ) {
          _this.url = data.data.url || '';
        }
      });
    }
  }
}

Проверяйте с осторожностью, на этот раз он включился, и он включился. Не могу сказать, что я счастлив, я в целом доволен.

Однако в следующую секунду я обнаружил, что слишком счастлив: окно открывалось, но страница в новом окне всегда находилась в состоянии анимации загрузки. Раньше я думал, что эта анимация загрузки была довольно красивой.Это была анимация большого круга без веерообразных непрерывно съедающих маленьких кругов, выстроенных один за другим.Теперь я думаю, что это съедает слишком много.

Улыбка меняется. Забудь об этом, перестань смеяться.

На этот раз бесполезно искать поисковую систему, обнаруживать вышеуказанную проблему, потому чтоНовое открытое окно сохранит sessionStorage старого окна.(Это выходит за рамки этого сообщения о том, почему sessionStorage предотвращает загрузку моей новой страницы). Зная причину, решение простое, просто очистите sessionStorage нового окна перед перенаправлением. То есть эта строка кода в приведенном выше кодеthis.newWin.location.href = newVal;добавить строку передthis.newWin.sessionStorage.clear()Достаточно. Код не будет опубликован.

В этом тесте не было ничего плохого.

Суммировать

Браузер будет блокировать открытие новых окон для защиты пользовательского опыта и может блокировать некоторые рекламные объявления. Обратите внимание, что ссылка на новое окноnewWinНа самом деле новыйwindowобъект, естественно, можно использовать вышеуказанный четкийsessionStorageМетоды. больше оwindowЗнания об объектах, такие как связь между новым окном и окном, которое его открывает, можно найти в главе 8, разделе 1 книги Advanced Javascript Programming.