vue不⽤iframe⽤什么代替_Vue中对iframe实现keepalive⽆刷
新的⽅法
前⾔
最近⼀个需求,需要在Vue 项⽬中加⼊含有iframe 的页⾯,同时在路由切换的过程中,要求iframe的内容不会被刷新 。⼀开始使⽤了Vue ⾃带的keep- alive发现没有⽤,于是⾃⼰研究了⼀下解决⽅案。。。。。。
Vue的keep-alive原理
要实现对保持iframe页的状态。我们先搞清楚为什么Vue的keep-alive不能凑效。keep-alive原理是把组件⾥的节点信息保留在了VNode (在内存⾥),在需要渲染时候从Vnode渲染到真实DOM上。iframe页⾥的内容并不属于节点的信息,所以使⽤keep-alive依然会重新渲染iframe内的内容。另外 ,我也尝试有过想法:如果把整个iframe节点保存起来,然后需要切换时把它渲染到⽬标节点上,能否实现iframe 页不被刷新呢?————也是不可⾏的,iframe每⼀次渲染就相当于打开⼀个新的⽹页窗⼝,即使把节点保存下来,在渲染时iframe页还是刷新的。
实现的思路
既然保持iframe页⾥的状态很难实现,在这个时候我想到了⼀个别的⽅法。能否在Vue的route-view节点上动点⼿脚?使得在切换⾮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: '
Index
' }
const routes = [
// 含有iframe的两个页⾯
{
path: '/f1',
name: 'f1'
},
// 含有iframe的两个页⾯
{
path: '/f2',
name: 'f2'
},
{
path: '/index',
component: Index
}
]
const router = new VueRouter({
routes
});
Vue.u(VueRouter);
道路工程施工方案new Vue({
render: h => h(App),
router
}).$mount('#app')
根组件:
Go to F1
Go to F2
Go to Index
import F1 from './components/f1';
import F2 from './components/f2';
export default {
name: 'app',
components: {
F1,
F2
},
}
上⾯代码简单来说,关键的地⽅⾸先是main.js初始化路由时,对iframe页不填写属性component,这样页⾯就是空⽩的。然后在router-view 节点旁边渲染iframe页组件,使⽤$route.path判断当前路由的指向,控制iframe页的显⽰与隐藏 。
上⾯代码简单的解决了问题,但还有⼀些地⽅可以优化:
iframe页在根节点App.vue⼀渲染时已经渲染 了,对此iframe页可以做成懒加载 ,只有在进⼊过相应页⾯了触发渲染,并且渲染过之后就⽤v-show切换显⽰与隐藏
每当增加⼀个iframe页都要增加⼀段的组件引⼊注册和调⽤的代码。⽐较繁琐 。我们⽬标应该做到每增加⼀个iframe页,只需要添加尽量少的代码。这⾥思路是:
在路由配置中定义⼀个属性,⽤于标识该页⾯是否含有iframe 的页⾯
根据标识,iframe页组件⾃动动态注册和渲染 ,⽆需再⼿写额外的代码
白雪战士router-view和iframe切换的逻辑封装成新组件 ,⽤它替代原有的router-view
我们先修改router的配置,增加⼀个属性名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: '
Index
' }
}
]
const router = new VueRouter({
routes // (缩写)相当于 routes: routes
});
new Vue({
render: h => h(App),
router
}).$mount('#app')
接下来我们第⼆步和第三步结合在⼀起,封装新的组件iframe-router-view.vue:v-for="item in hasOpenComponentsArr"
:key="item.name"
:is="item.name"
v-show="$route.path === item.path"
>
import Vue from 'vue/dist/vue.js'
export default {
created() {
// 设置iframe页的数组对象
const componentsArr = ComponentsArr(); componentsArr.forEach((item) => {
});
// 判断当前路由是否iframe页
this.isOpenIframePage();
},
data() {
return {
componentsArr: [] // 含有iframe的页⾯
}
},
watch: {
$route() {
// 判断当前路由是否iframe页
this.isOpenIframePage();
}
},
computed: {
// 实现懒加载,只渲染已经打开过(hasOpen:true)的iframe页hasOpenComponentsArr() {
ponentsArr.filter(item => item.hasOpen); }
},
methods: {
// 根据当前路由设置hasOpen
isOpenIframePage() {
const target = ponentsArr.find(item => {
return item.path === this.$route.path
});
if (target && !target.hasOpen) {
蟒target.hasOpen = true;
}
},
// 遍历路由的所有页⾯,把含有iframeComponent标识的收集起来
getComponentsArr() {
const router = this.$router;
const routes = utes;
const iframeArr = routes.filter(item => item.iframeComponent);
return iframeArr.map((item) => {
写规范字
const name = item.name || place('/', '');
return {
name: name,
意大利香肠披萨path: item.path,
hasOpen: fal, // 是否打开过,默认fal
component: item.iframeComponent // 组件⽂件的引⽤
};
});
}
}
}
该组件主要做的是根据main.ja⾥的routes⽣成⼀个只含有iframe页的数组对象。
watch上监听$route,判断当前页⾯在iframe页列表⾥的话就设置hasOpen属性为true,渲染该组件⽤v-show="$route.path === item.path"切换iframe页的显⽰与隐藏。
逻辑并不复杂,这⾥就不多赘述。
结语
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。