предисловие
Самое последнее требование, которое должно бытьVueдобавил в проектсодержит фреймыСтраница, при этом в процессе переключения роутинга требует содержимое iframeне будет обновляться. В начале я использовал поддержку активности, которая поставляется с Vue, и нашел ее бесполезной, поэтому я сам исследовал решение. . . . . .
Принцип поддержания активности Vue
Для достижения статуса сохранения страницы IFRAME. Давайте узнаем, почему живой Vue живой не может работать, если. Aff-alive - это принципиальный компонент в информации у узла, сохраненной вVNode(В памяти), рендеринг из vNode в настоящий DOM во время рендеринга. Содержимое страницы iFrame не относится к информации узла, поэтому использование Keep-Alive по-прежнему отображает содержимое в IFRAME.Кроме того, я также попытался иметь идею: если вы сохраняете весь узел iframe, а затем рендерите его на целевой узел, когда вам нужно переключиться, страница iframe не будет обновляться? ——Это также невозможно.Каждый раз, когда рендерится iframe, это эквивалентно открытию нового окна веб-страницы.Даже если узел сохраняется, страница iframe обновляется во время рендеринга.
идея реализации
Поскольку поддерживать состояние на странице iframe сложно, в этот раз я подумал о другом методе. Можете ли вы что-нибудь сделать с узлом просмотра маршрута Vue? переключитьсястраницы без iframeПри использовании маршрутизации Vue при переключенииiFrame-страницаиспользовать, когдаv-showПереключите отображение и скрытие, делая узел iframeникогда не удалялся, который сохраняет состояние iframe.
Мы просто реализуем вышеуказанные эффекты и приведенный выше код:
Запись main.js:
import Vue from 'vue/dist/vue.js'
import App from './App.vue'
import VueRouter from 'vue-router';
const Index = { template: '<div>Index</div>' }
const routes = [
// 含有iframe的两个页面
{
path: '/f1',
name: 'f1'
},
// 含有iframe的两个页面
{
path: '/f2',
name: 'f2'
},
{
path: '/index',
component: Index
}
]
const router = new VueRouter({
routes
});
Vue.use(VueRouter);
new Vue({
render: h => h(App),
router
}).$mount('#app')
корневой компонент:
<template>
<div id="app">
<div class="nav">
<router-link class="router" to="/f1">Go to F1</router-link>
<router-link class="router" to="/f2">Go to F2</router-link>
<router-link class="router" to="/index">Go to Index</router-link>
</div>
<keep-alive>
<!-- Vue的路由 -->
<router-view></router-view>
</keep-alive>
<!-- iframe页面 -->
<f1 v-show="$route.path == '/f1'"></f1>
<f2 v-show="$route.path == '/f2'"></f2>
</div>
</template>
<script>
import F1 from './components/f1';
import F2 from './components/f2';
export default {
name: 'app',
components: {
F1,
F2
},
}
</script>
Приведенный выше код прост, ключевым моментом является то, что когда main.js инициализирует маршрут, компонент атрибута не заполняется на странице iframe, поэтому страница пуста. затем вrouter-viewОтобразите компонент страницы iframe рядом с узлом, используйте $route.path для определения направления текущего маршрута и управления страницей iframe.показать и скрыть.
оптимизация
Приведенный выше код просто решает проблему, но все же есть места, которые можно оптимизировать:
- Когда страница iframe отображается в корневом узле App.vueуже отрендеренныйТеперь эту страницу iframe можно сделатьленивая загрузка, запускать рендеринг только после входа на соответствующую страницу и использовать v-show для переключения отображения и скрытия после рендеринга
- Всякий раз, когда добавляется страница IFrame, необходимо добавить раздел компонентов для введения кода для регистрации и вызова. Сравниватьгромоздкий. Наша цель — добавить как можно меньше кода для каждой дополнительной страницы iframe. Идея здесь такова:
- Определите свойство в конфигурации маршрута дляОпределяет, содержит ли страница iframeстраница
- Согласно идентификатору, компонент страницы iframeАвтоматическая динамическая регистрация и рендеринг, не нужно писать дополнительный код
- Просмотр маршрутизатора и IFrame Логикановые компоненты, используй этоЗамените исходный маршрутизатор-представление
Сначала мы изменим конфигурацию маршрутизатора и добавим имя свойства iframeComponent, чтобы указать, следует ли включать iframe. Значением этого свойства является ссылка на файл компонента.
main.js:
import F1 from './components/f1';
import F2 from './components/f2';
const routes = [
{
path: '/f1',
name: 'f1',
iframeComponent: F1 // 用于标识是否含有iframe页
},
{
path: '/f2',
name: 'f2',
iframeComponent: F2 // 用于标识是否含有iframe页
},
{
path: '/index',
component: { template: '<div>Index</div>' }
}
]
const router = new VueRouter({
routes // (缩写)相当于 routes: routes
});
new Vue({
render: h => h(App),
router
}).$mount('#app')
Затем мы объединяем второй и третий шаги для инкапсуляции нового компонента iframe-router-view.vue:
<template>
<div>
<!-- Vue的router-view -->
<keep-alive>
<router-view></router-view>
</keep-alive>
<!-- iframe页 -->
<component
v-for="item in hasOpenComponentsArr"
:key="item.name"
:is="item.name"
v-show="$route.path === item.path"
></component>
</div>
</template>
<script>
import Vue from 'vue/dist/vue.js'
export default {
created() {
// 设置iframe页的数组对象
const componentsArr = this.getComponentsArr();
componentsArr.forEach((item) => {
Vue.component(item.name, item.component);
});
this.componentsArr = componentsArr;
// 判断当前路由是否iframe页
this.isOpenIframePage();
},
data() {
return {
componentsArr: [] // 含有iframe的页面
}
},
watch: {
$route() {
// 判断当前路由是否iframe页
this.isOpenIframePage();
}
},
computed: {
// 实现懒加载,只渲染已经打开过(hasOpen:true)的iframe页
hasOpenComponentsArr() {
return this.componentsArr.filter(item => item.hasOpen);
}
},
methods: {
// 根据当前路由设置hasOpen
isOpenIframePage() {
const target = this.componentsArr.find(item => {
return item.path === this.$route.path
});
if (target && !target.hasOpen) {
target.hasOpen = true;
}
},
// 遍历路由的所有页面,把含有iframeComponent标识的收集起来
getComponentsArr() {
const router = this.$router;
const routes = router.options.routes;
const iframeArr = routes.filter(item => item.iframeComponent);
return iframeArr.map((item) => {
const name = item.name || item.path.replace('/', '');
return {
name: name,
path: item.path,
hasOpen: false, // 是否打开过,默认false
component: item.iframeComponent // 组件文件的引用
};
});
}
}
}
</script>
- Основная цель этого компонента состоит в том, чтобы генерировать объект массива, содержащий только страницы IFrame в соответствии с маршрутами в Main.ja.
- Прослушивание $ route на Watch, определить, есть ли текущая страница в списке страниц iFrame, установить для свойства Hasopen значение true, визуализировать компонент
- Используйте v-show="$route.path === item.path" для переключения отображения и скрытия страницы iframe.
Логика не сложная, поэтому я не буду здесь вдаваться в подробности.
Эпилог
Если у вас есть лучший метод реализации, или если у меня есть какие-то ошибки, которые нужно исправить, добро пожаловать в общение. Код демо выше выложен на личном гитхабеGitHub.com/Feather Letter16449196…