Home > Web Front-end > JS Tutorial > How to implement integrated Iframe page using Vue

How to implement integrated Iframe page using Vue

亚连
Release: 2018-06-21 11:43:08
Original
3672 people have browsed it

This article mainly introduces examples of how Vue integrates Iframe pages. The editor thinks it is quite good. Now I will share it with you and give it as a reference. Let’s follow the editor and take a look.

1. Project requirements

We will switch to the vue framework later. Before, some functional pages used jsp pages. Written, and our management system needs to support both the Vue URL and the jsp pages after these releases

The other thing is that when switching tabs back, the previously entered things still exist

System page screenshot

2. Implementation idea

In response to this problem, our initial implementation idea was to write a Common components of iframe, and then pass the URLs of different http pages to switch, but this does not satisfy the second point. We found that as long as we switch the route of vue, and then switch back to the http page, the src attribute in the iframe The page will be refreshed, and there is no way to retain things, so we have the following implementation idea

We added an iframeTemp component at the same level as vue's router-view, which is actually a tab component of elementUI, and then Hide the style of the tab component header under our menu bar

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

<template>

 <!--路由渲染的功能模块区域-->

 <p class="router-out-content">

  <!--缓存部分页面的写法-->

  <keep-alive>

   <router-view v-show="!showIframe" class="position router-content" v-if="$route.meta.keepAlive"></router-view>

  </keep-alive>

  <router-view v-show="!showIframe" class="position router-content" v-if="!$route.meta.keepAlive"></router-view>

  <!--兼容系统外部页面-->

  <iframe-temp v-show="showIframe"></iframe-temp>

 </p>

</template>

<style scoped lang="scss">

 .position {

  position: relative

 }

 

 .router-out-content {

  position: static;

 }

</style>

<script>

import { mapState } from &#39;vuex&#39;

import iframeTemp from &#39;@/containers/main/IframeTemplate.vue&#39;

export default {

 data() {

  return {}

 },

 components: {

  iframeTemp

 },

 computed: {

  ...mapState([

   &#39;showIframe&#39;

  ])

 }

}

</script>

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

/*

 * IframeTemplate.vue组件的内部

 **/

 

 <template>

 <!--iframe页面展示区域-->

 <p id="fwIframe">

  <!--<Tabs class="full temporary-tabs" v-model="store.state.iframeSelectTab" type="card">-->

  <Tabs class="full temporary-tabs" :value="iframeSelectTab" type="card">

   <TabPane

    v-for="(item, index) in iframeTabData"

    :key="item.tag"

    :label="item.name"

    :name="item.tag"

   >

    <iframe :key="item.tag" v-once :src="item.url" frameborder="0"></iframe>

   </TabPane>

  </Tabs>

 </p>

</template>

<style lang="scss">

 #fwIframe {

  /*测试位置的时候显示这段--开始*/

  /*width: 100%;*/

  /*height: 100%;*/

  /*background-color: red;*/

  /*display: block !important;*/

  /*测试位置的时候显示这段--结束*/

  position: absolute;

  left: 0;

  right: 0;

  top: 45px;

  bottom: 0;

  z-index: 5000 !important;

  .el-tab-pane {

   height: 100%;

   width: 100%;

   iframe {

    /*height: auto;*/

    min-height: 600px;

    /*height: calc(100% - 45px);*/

    width: 100%;

   }

 

  }

  .full {

   position: relative;

   left: 0;

   right: 0;

   top: 0;

   bottom: 0;

  }

 }

</style>

<script>

 

 // selectTabCode=>iframeSelectTab

 // tabsList=>iframeTabData

 import {mapState} from &#39;vuex&#39;

 import * as mainConst from &#39;@/store/mainConst.js&#39;

 export default{

  data(){

   return {

//    tabsList: [],

//    selectTabCode: &#39;&#39;

   }

  },

  computed: {

   ...mapState([

    &#39;iframeTabData&#39;,

    &#39;iframeSelectTab&#39;,

    &#39;navTabData&#39;,

    &#39;systemName&#39;

   ])

  },

  mounted(){

   const _this = this

 

   // 1、监听添加iframe中tab的广播

   this.$root.bus.$on(&#39;addIframeTab&#39;, function (item) {

 

    // _this.tabsList.push(item)

    // _this.selectTabCode = item.tag

    _this.$store.commit(mainConst.M_IFRAME_PUSH_TAB, item)

    _this.$store.commit(mainConst.M_IFRAME_CHANGE_SELECTCODE, item.tag)

   })

 

   // 2、监听切换iframe中tab的广播

   this.$root.bus.$on(&#39;changeIframeTab&#39;, function (tag) {

    _this.$store.commit(mainConst.M_IFRAME_CHANGE_SELECTCODE, tag)

 

   })

   // 3、监听删除iframe中tab的广播

   this.$root.bus.$on(&#39;deleteIframeTab&#39;, function (obj) {

    // 1、删除iframe中的指定tab页面

    _this.$store.commit(mainConst.M_IFRAME_DELETE_TAB, obj)

    // _this.tabsList = _this.tabsList.filter(tab => tab.tag !== obj.tag)

 

    // 2、如果删除的一级tab不是当前激活的一级tab,TabsTemeplate中的一级tab删除事件已经在vuex中删除了,不需要做路由跳转操作了

    let index = obj.index

    for (let i = 0; i < _this.navTabData.length; i++) {

     if (_this.navTabData[i].active) {

      return

     }

    }

 

    // 3、如果删除的一级tab是当前激活的一级tab,

    const con = _this.navTabData[index - 1] || _this.navTabData[index]

    let url = `/${_this.systemName}`

    if (con) {

     // 还有其他的一级tab,就赋值其他的一级tab的url,探后跳转

     url = con.url

     con.active = true

 

     // 如果还有其他一级的tab,那么还要判断跳转的页面是不是iframe

     if (url.toLowerCase().indexOf("/iframe") == 0) {

      // 如果是iframe页面,显示iframe,广播iframe的切换tab切换事件,路由进行跳转

      _this.$store.commit(mainConst.M_SHOW_IFRAME)

      _this.$root.bus.$emit("changeIframeTab", url.slice(8))

 

     } else {

      // 如果不是iframe页面,隐藏iframe,路由进行跳转

      _this.$store.commit(mainConst.M_HIDE_IFRAME)

      // _this.$store.commit(mainConst.M_UPDATE_NAVTABDATA, {navIndex: index})

     }

    }

    else {

     // 没有其他的一级tab,直接隐藏iframe,跳首页

     _this.$store.commit(mainConst.M_HIDE_IFRAME)

    }

 

    _this.$router.push(url)

   })

  }

 }

</script>

Copy after login

The display, hiding and tab switching of the ifram component are all implemented by universal vuex and bus event broadcast

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

/*

 * mainConst.js

 **/

 

 

/*****************************getter常量****************************************/

export const G_GET_NAVTABDATA = &#39;G_GET_NAVTABDATA&#39;

 

/*****************************mutations常量*************************************/

// 一级tab处理

export const M_PUSH_NAVTABDATA = &#39;M_PUSH_NAVTABDATA&#39;

export const M_DELETE_NAVTABDATA = &#39;M_DELETE_NAVTABDATA&#39;

export const M_UPDATE_NAVTABDATA = &#39;M_UPDATE_NAVTABDATA&#39;

 

// iframe切换处理

export const M_SHOW_IFRAME = &#39;M_SHOW_IFRAME&#39;

export const M_HIDE_IFRAME = &#39;M_HIDE_IFRAME&#39;

 

// iframe添加,删除,选择处理

export const M_IFRAME_PUSH_TAB=&#39;M_IFRAME_PUSH_TAB&#39;

export const M_IFRAME_DELETE_TAB=&#39;M_IFRAME_DELETE_TAB&#39;

export const M_IFRAME_CHANGE_SELECTCODE=&#39;M_IFRAME_CHANGE_SELECTCODE&#39;

 

// 设置全局系统变量

export const M_SET_SYSTEMNAME = &#39;M_SET_SYSTEMNAME&#39;

 

/*****************************actions常量***************************************/

// export const A_REQUEST_DATA = &#39;A_REQUEST_DATA&#39;

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

/*

 * mainModule.js

 **/

 

import * as mainConst from &#39;./mainConst.js&#39;

 

export default {

 state: {

  // 一级Tab导航数据集合

  navTabData: [],

  // 进入的主系统前缀

  systemName:&#39;&#39;,

  // 控制路由同级的Iframe的显示隐藏

  showIframe: false,

  // iframe页面中的选中页签的code值

  iframeSelectTab:&#39;&#39;,

  // iframe页面的tab数据集合

  iframeTabData:[]

 

 },

 getters: {

  [mainConst.G_GET_NAVTABDATA](state, getters){

   return state.navTabData

  }

 },

 mutations: {

  // 一级tab处理

  [mainConst.M_UPDATE_NAVTABDATA](state, payload){

   const index = payload.navIndex

   state.navTabData.forEach((item)=> {

    item.active = false

   })

 

   // 当你利用索引直接设置一个项时是不能触发视图的从新渲染的,下面是老方法和解决办法

   // state.navTabData[index].active=true

   let newItem = Object.assign({}, state.navTabData[index], {active: true})

   // console.log(newItem, &#39;store newItem&#39;)

   state.navTabData.splice(index, 1, newItem)

  },

  [mainConst.M_PUSH_NAVTABDATA] (state, payload) {

   state.navTabData.push(payload)

  },

  [mainConst.M_DELETE_NAVTABDATA] (state, payload) {

   state.navTabData.splice(payload.navIndex, 1)

  },

  // Iframe显示隐藏切换处理

  [mainConst.M_SHOW_IFRAME] (state, payload) {

   state.showIframe = true

  },

  [mainConst.M_HIDE_IFRAME] (state, payload) {

   state.showIframe = false

  },

  // Iframe添加,删除,选中处理

  [mainConst.M_IFRAME_PUSH_TAB] (state, payload) {

   state.iframeTabData.push(payload)

  },

  [mainConst.M_IFRAME_DELETE_TAB] (state, payload) {

   state.iframeTabData = state.iframeTabData.filter(tab => tab.tag !== payload.tag)

  },

  [mainConst.M_IFRAME_CHANGE_SELECTCODE] (state, payload) {

   state.iframeSelectTab=payload

  },

  // 设置全局system变量

  [mainConst.M_SET_SYSTEMNAME] (state, payload) {

   state.systemName=payload

  }

 },

 actions: {

  // actions的最终功能是修改state,但是它不直接修改state,而是调用mutations

  // async [aboutConst.A_REQUEST_DATA]({dispatch,commit}) {

  //  commit(aboutMutations.REQUEST_LOADING)

  //  await service.getMovieListData(&#39;{"movieType":"in_theaters","pageIndex":2,"start":0,"count":10}&#39;)

  //  console.log(333333)

  //  await function(){setTimeout(function () {

  //   commit(aboutMutations.REQUEST_FAILD)

  //  },6000)}()

  //  console.log(66666)

  // }

 

  // actions的最终功能是修改state,但是它不直接修改state,而是调用mutations

  // async [aboutConst.A_REQUEST_DATA]({dispatch,commit}) {

  //  commit(aboutMutations.REQUEST_LOADING)

  //  await service.getMovieListData(&#39;{"movieType":"in_theaters","pageIndex":2,"start":0,"count":10}&#39;)

  //  console.log(333333)

  //  await function(){setTimeout(function () {

  //   commit(aboutMutations.REQUEST_FAILD)

  //  },6000)}()

  //  console.log(66666)

  // }

 }

}

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

/*

 * 三级菜单的点击处理

 **/

<template>

 <!--三级菜单导航功能-->

 <p class="main-nav f14 clearfix" @mouseleave="funMenu.menuIsShow=false">

  <p class="f_l lt-tab">

   <ul class="l-nav clearfix">

    <li class="main f_l">

     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="f16 fun" @click="getMainMenu">功能导航</a>

     <p class="more-menu clearfix" v-show="funMenu.firstMenu.length&&funMenu.menuIsShow">

      <!--一级导航-->

      <ul class="first-menu f_l">

       <li v-for="(item,index) in funMenu.firstMenu" @mouseover="clickByMenu($event,item,&#39;firstMenu&#39;)">

        <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" :class="{active:item.active}" :index="index">{{item.resourceName}}</a>

       </li>

      </ul>

      <!--二级导航-->

      <ul class="next-menu f_l" v-show="funMenu.nextMenu.length">

       <li

        v-for="(item,index) in funMenu.nextMenu"

        @mouseover="clickByMenu($event,item,&#39;nextMenu&#39;)"

        @click="clickMenuJump(funMenu.nextMenu, item)"

       >

        <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" :class="{active:item.active}" :index="index">{{item.resourceName}}</a>

       </li>

      </ul>

      <!--三级导航-->

      <!--存在四级导航-->

      <p class="last-menu f_l dl" v-show="funMenu.lastMenu.length">

       <p v-for="(item,index) in funMenu.lastMenu" class="dt">

        <p v-if="item.childFuncs.length">

         <span>{{item.resourceName }}</span>

         <ul class="dd">

          <li v-for="(item,index) in item.childFuncs"

           @click="clickByMenu($event,item,&#39;lastMenu&#39;)">

           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >{{item.resourceName}}</a>

           <!--:class="{active:item.active}"-->

          </li>

         </ul>

        </p>

        <!--三级导航可点击-->

        <p v-else>

         <ul class="dd">

          <li @click="clickByMenu($event,item,&#39;lastMenu&#39;)">

           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >{{item.resourceName}}</a>

           <!--:class="{active:item.active}"-->

          </li>

         </ul>

        </p>

 

       </p>

      </p>

     </p>

    </li>

    <li class="nav-index f_l">

     <!--<router-link :to="&#39;/&#39;+$store.state.systemName">首页</router-link>-->

     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="goHome">首页</a>

    </li>

   </ul>

  </p>

 </p>

</template>

<style scoped lang="scss">

 .main-nav {

  position: relative;

  height: 42px;

  line-height: 42px;

  background: #eee;

  border-bottom: 1px solid #ddd;

 }

 

 .main-nav a {

  color: #303e51;

  text-decoration: none;

 }

 

 .main-nav a:hover {

  color: #438eb9;

 }

 

 .main-nav .main {

  /*padding: 0 16px;*/

  text-align: center;

  border-right: 1px solid #ddd;

  position: relative;

  background: #eee;

  width: 122px;

 }

 

 .main-nav .main.active, .main-nav .main:hover {

  background: white;

 }

 

 .main-nav .more-menu {

  position: fixed;

  top: 84px;

  left: 0;

  max-height: 500px;

  bottom: 124px;

  z-index: 998;

  background: #fff;

  border: 1px solid #ddd;

  border-left: none;

  border-top: 0;

  overflow: hidden;

  box-shadow: 1px 1px 10px #ddd;

 }

 

 .main-nav .more-menu ul, .main-nav .more-menu .dl {

  text-align: left;

  overflow: auto;

 }

 

 .main-nav .more-menu a {

  font-size: 14px;

  color: #303e51;

  text-decoration: none;

 }

 

 .main-nav .more-menu a:hover, .main-nav .more-menu a.active {

  color: rgb(46, 167, 224);

 }

 

 .main-nav .more-menu .first-menu {

  height: 100%;

  border-right: 1px solid #ddd;

  box-shadow: -1px 0px 5px #ddd inset;

  /*width: 138px;*/

 }

 

 .main-nav .more-menu .first-menu li {

  height: 36px;

  line-height: 36px;

  margin: 0 15px 0 6px;

  min-width: 94px;

 }

 

 .main-nav .more-menu .first-menu a {

  display: block;

  background: url(../../asserts/images/home/main/icon_1.png) no-repeat 5px center;

  width: 100%;

  height: 100%;

  border-bottom: 1px solid #dddddd;

  padding-left: 20px;

  box-sizing: border-box;

  text-overflow: ellipsis;

  overflow: hidden;

  white-space: nowrap;

  text-indent: 5px;

 }

 

 .main-nav .more-menu .first-menu a.active, .main-nav .more-menu .first-menu a:hover {

  background: url(../../asserts/images/home/main/icon_2.png) no-repeat 5px center rgb(46, 167, 224);

  color: white;

  border: 0;

 }

 

 .main-nav .more-menu .next-menu {

  height: 100%;

  border-right: 1px solid #ddd;

  box-shadow: -1px 0px 5px #ddd inset;

  /*width: 138px;*/

  line-height: 14px;

 }

 

 .main-nav .more-menu .next-menu li:first-child {

  margin-top: 10px;

 }

 

 .main-nav .more-menu .next-menu li {

  margin-bottom: 16px;

  margin-left: 16px;

 }

 

 .main-nav .more-menu .next-menu li a {

  border-left: 2px solid transparent;

  padding-left: 10px;

  margin-right: 24px;

 }

 

 .main-nav .more-menu .next-menu li a:hover, .main-nav .more-menu .next-menu li a.active {

  border-left: 2px solid rgb(46, 167, 224);

 }

 

 .main-nav .more-menu .last-menu {

  height: 100%;

  min-width: 288px;

  line-height: 14px;

 }

 

 .main-nav .more-menu .last-menu .dt {

  margin-left: 16px;

  margin-top: 10px;

  span {

   color: #566678;

  }

 }

 

 .main-nav .more-menu .last-menu .dd {

  color: #7a8897;

  margin-top: 16px;

  margin-left: 4px;

  > li {

   margin-bottom: 16px;

   a {

    border-left: 2px solid transparent;

    padding-left: 6px;

    margin-right: 16px;

    &:hover, &.active {

     border-color: #2ea7e0;

    }

   }

  }

 }

 

 /*.main-nav .more-menu .last-menu dd a:hover,.main-nav .more-menu .last-menu dd a.active{*/

 /*border-left: 2px solid rgb(46,167,224);*/

 /*}*/

 .main-nav .main .fun {

  width: 100%;

  height: 100%;

  display: block;

 }

 

 .main-nav .main .fun:before {

  content: "";

  width: 18px;

  height: 18px;

  background: url("../../asserts/images/home/main/icon-all.png");

  background-position: -89px -7px;

  display: inline-block;

  margin-right: 10px;

  margin-top: 2px;

  vertical-align: text-top;

 }

 

 .main-nav .l-nav {

  z-index: 2;

 }

 

 .main-nav .nav-index {

  width: 90px;

  text-align: center;

  position: relative;

  background: #eee;

 }

 

 .main-nav .nav-index:after {

  content: "";

  width: 8px;

  height: 40px;

  background: url(../../asserts/images/home/main/shadow-l.png);

  position: absolute;

  top: 2px;

  left: 90px;

 }

 

 .main-nav .lt-tab {

  position: absolute;

  left: 0;

  z-index: 2;

  border-bottom: 1px solid #ddd;

 }

 

 /*tab--------*/

 .main-nav .ct-tab {

  position: absolute;

  z-index: 1;

  left: 213px;

  width: 10000000px;

 }

 

 .main-nav .ct-tab .ct-ul {

 

 }

 

 .main-nav .ct-tab .ct-ul li {

  position: relative;

  float: left;

 }

 

 .main-nav .ct-tab .ct-ul li a {

  height: 24px;

  line-height: 24px;

  margin: 9px 0;

  min-width: 90px;

  /*max-width: 190px;*/

  border-right: 1px solid #ddd;

  display: block;

  text-align: center;

  position: relative;

 }

 

 .main-nav .ct-tab .ct-ul li a i {

  display: none;

 }

 

 .main-nav .ct-tab .ct-ul li a i {

  display: none;

 }

 

 .main-nav .ct-tab .ct-ul li a .content {

  display: block;

  max-width: 190px;

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover {

  z-index: 1;

 }

 

 .main-nav .ct-tab .ct-ul li:first-child a:hover, .main-nav .ct-tab li:first-child a.active {

  margin-left: 0;

  margin-right: 0;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover, .main-nav .ct-tab li a.active {

  max-width: 250px;

  display: block;

  text-align: center;

  position: relative;

  border: 0;

  margin: 0 -20px;

  margin-top: 4px;

  color: black;

  padding: 0;

 }

 

 .main-nav .ct-tab .padding {

  width: auto;

  padding: 0 16px;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover > i, .main-nav .ct-tab .ct-ul li a.active > i {

  display: inline-block;

  width: 34px;

  height: 37px;

  float: left;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover .line-l {

  background: url(../../asserts/images/home/main/line_left.png) no-repeat;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover .line-r {

  background: url(../../asserts/images/home/main/line_right.png) no-repeat;

 }

 

 .main-nav .ct-tab .ct-ul li a.active .line-l {

  background: url(../../asserts/images/home/main/line_sel_left.png) no-repeat;

 }

 

 .main-nav .ct-tab .ct-ul li a.active .line-r {

  background: url(../../asserts/images/home/main/line_sel_right.png) no-repeat;

 }

 

 .main-nav .ct-tab .ct-ul li a:hover .content, .main-nav .ct-tab li a.active .content {

  border-top: 1px solid #ddd;

  float: left;

  line-height: 36px;

  min-width: 60px;

  max-width: 150px;

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

  background: rgb(245, 245, 245);

 }

 

 .main-nav .ct-tab .ct-ul li a:hover .cha, .main-nav .ct-tab .ct-ul li a.active .cha {

  background: rgb(245, 245, 245);

  width: 20px;

  height: 36px;

  line-height: 36px;

  border-top: 1px solid #ddd;

  padding-left: 7px;

  color: #303e51;

 }

 

 .main-nav .ct-tab .ct-ul li a.active .content, .main-nav .ct-tab .ct-ul li a.active .cha {

  background: white;

 }

 

 .main-nav .ct-tab .ct-ul li a .cha {

  color: #eee;

 }

 

 .main-nav .ct-tab .ct-ul li a .cha:hover {

  color: black;

 }

 

 .main-nav .ct-tab .ct-ul li a.active {

  z-index: 2;

 }

</style>

<script>

 import axios from &#39;axios&#39;

 import { mapState} from &#39;vuex&#39;

 import * as mainConst from &#39;@/store/mainConst.js&#39;

 import config from &#39;@/config/index.js&#39;

 import storage from &#39;@/utils/storage.js&#39;

 export default{

  data(){

   return {

    funMenu: {

     // 一级菜单

     firstMenu: [],

     // 二级菜单

     nextMenu: [],

     // 三级菜单

     lastMenu: [],

     // 是否显示

     menuIsShow: true

    }

   }

  },

  computed: mapState({

   // 箭头函数可使代码更简练

   funcMenuList: state => state.funcMenuList,

  }),

  methods: {

   // 跳转首页

   goHome(){

    // 跳转首页就关闭iframe

    this.$store.commit(mainConst.M_HIDE_IFRAME)

    this.$router.push(`/${this.$store.state.systemName}`)

   },

   // ★★★★★调用方法获取三级菜单列表★★★★★

   getMainMenu(){

    var _this = this

    if (this.funMenu.firstMenu.length) {

     this.funMenu.menuIsShow = true

    } else {

     if (config.setting.funcMenu) {

      _this.funMenu.firstMenu = storage.getItem(&#39;hivescm.userAuthor&#39;).menus.funcs

     } else {

      axios.get("data/menu_json.json")

       .then(function (res) {

        _this.funMenu.firstMenu = res.data.result.funcs

       })

     }

    }

   },

   // 点击菜单展开下一级别列表事件

   clickByMenu(e, menuItem, level){

    let menuList = this.funMenu[level]

    switch (level) {

     case "firstMenu": {

      this.funMenu.nextMenu = this.getFirstAndNextVal(menuList, menuItem)

      this.funMenu.lastMenu = []

     }

      break

     case "nextMenu": {

      if (!menuItem.url.length) this.funMenu.lastMenu = this.getFirstAndNextVal(menuList, menuItem)

//      menuItem.url.length ? this.clickMenuJump(menuList, menuItem) : this.funMenu.lastMenu = this.getFirstAndNextVal(menuList, menuItem)

     }

      break

     case "lastMenu": {

      this.clickMenuJump(menuList, menuItem)

     }

      break

    }

   },

   // ★★★★★点击有url的菜单,跳转事件★★★★★

   clickMenuJump(menuList, menuItem){

    if (!menuItem.url.length) return

    this.funMenu.menuIsShow = false

    this.lastmenuChange(menuList, menuItem)

    let iframeTabItem = {}

    // 1、路由跳转和iframe的显示隐藏

    if (menuItem.url.toLowerCase().indexOf("/") != 0 || menuItem.url.toLowerCase().indexOf("/iframe") == 0) {

     // 判断如果是iframe的url,显示iframe

     // 定义一个新的item对象,防止对象的引用

     iframeTabItem = Object.assign({}, menuItem)

     this.$store.commit(mainConst.M_SHOW_IFRAME)

     // 待优化:应该有优化为手动赋值样式

     // (1)、此处利用router-view的特性,让一级tab变颜色

     // (2)、这个还是控制一级tab点击切换tab标签的重要因素

     // 因为原始的iframe的url已经改变,所以要保存到一个新的变量里面,如果已经有了就不需要在放了

     if (!menuItem.iframeUrl) {

      menuItem.iframeUrl = menuItem.url

      let userId = storage.getItem(&#39;hivescm.userAuthor&#39;).id

      let token = storage.getItem(&#39;hivescm.userAuthor&#39;).token

      iframeTabItem.url = `${menuItem.url}?userId=${userId}&token=${token}`

     } else {

      let userId = storage.getItem(&#39;hivescm.userAuthor&#39;).id

      let token = storage.getItem(&#39;hivescm.userAuthor&#39;).token

      iframeTabItem.url = `${menuItem.iframeUrl}?userId=${userId}&token=${token}`

      console.log(iframeTabItem.url)

//      iframeTabItem.url = menuItem.iframeUrl

     }

     menuItem.url = `/iframe/${menuItem.tag}`

     this.$router.push(`/iframe/${menuItem.tag}`)

 

    } else {

     // 判断如果是spa的url,隐藏iframe

     this.$store.commit(mainConst.M_HIDE_IFRAME)

     menuItem.url=`${menuItem.url}?permissionId=${menuItem.permissionId}`

     this.$router.push({path:menuItem.url,query:{permissionId:menuItem.permissionId}})

    }

 

    // 2、判断vuex中是否有重复的tab标签

    let navTabData = this.$store.state.navTabData

    for (let i = 0; i < navTabData.length; i++) {

     if (navTabData[i].url == menuItem.url) {

      // 已经有页签了,一级tab内容不重新渲染

      // 切换一级tab页签的激活样式

      this.$store.commit(mainConst.M_UPDATE_NAVTABDATA, {navIndex: i})

      // 从新计算一级tab位置

      this.$root.bus.$emit("clickLastMenu", menuItem)

 

      if (menuItem.url.toLowerCase().indexOf("/iframe") == 0) {

       // 如果已经iframe中的tab已经存在,那么触发iframe中的切换事件

//       this.$store.commit(mainConst.M_SHOW_IFRAME)

       this.$root.bus.$emit("changeIframeTab", menuItem.url.slice(8))

      }

      return

     }

    }

 

    // 3、向vuex中添加一级tab

    // 默认是否选中

    menuItem.active = true

    // 向一级tab中添加新的tab标签

    this.$store.commit(mainConst.M_PUSH_NAVTABDATA, menuItem)

    this.$store.commit(mainConst.M_UPDATE_NAVTABDATA, {navIndex: navTabData.length - 1})

    // 向iframe中的tab添加页签

    this.$root.bus.$emit("addIframeTab", iframeTabItem)

   },

   // 清空导航属性值,确保再次点击无选中样式及不匹配数据

   lastmenuChange(menuList, menuItem){

    this.funMenu.firstMenu.forEach(function (item) {

     item.active = false

    })

    this.funMenu.nextMenu.forEach(function (item) {

     item.active = false

    })

    this.funMenu.lastMenu.forEach(function (item) {

     item.active = false

    })

    this.funMenu.nextMenu = []

    this.funMenu.lastMenu = []

   },

   // 增加选中样式及赋值下级菜单

   getFirstAndNextVal(menuList, menuItem){

    var childFuncs = []

    for (let i = 0; i < menuList.length; i++) {

     if (menuList[i].permissionId == menuItem.permissionId) {

      menuList[i].active = true

      childFuncs = menuList[i].childFuncs || []

     } else {

      menuList[i].active = false

     }

    }

    return childFuncs

   }

  }

 }

</script>

Copy after login

We also need to add a useless route because our anchor has to change

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

/*

 * iframe/router/index.js

 */

const systemNamePrefix = "iframe_"

import MainContainer from &#39;@/containers/MainContainer.vue&#39;

import IframeComponent from &#39;@Iframe/containers/IframeComponent.vue&#39;

 

export default [

 {

  path: &#39;/iframe&#39;,

  component: MainContainer,

  children: [

   {path: &#39;:tag&#39;, component: IframeComponent, meta: {requiresAuth: true, keepAlive: true}},

  ],

  meta: {requiresAuth: true}

 }

]

Copy after login

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

/*

 * iframeComponent.vue,一个没用的vue文件,只是为了让浏览器中的锚记发生变化

 */

 

<template>

 <p v-if="isCache">

  <span>{{src}}</span>

 </p>

</template>

<style scoped lang="scss">

</style>

<script>

 export default{

  data(){

   return {

    isCache: true,

    src: &#39;&#39;

   }

  },

  created(){

  },

  mounted(){

   // 1、这个页面存在的意义就是在iframe页面切换的时候,路由可以跳转过去用,没有实际大的作用,但是得有这个页面

   // 2、iframe的Tab页面的z-index比这个页面的高

   this.src=this.$route.params.tag

  }

 }

</script>

Copy after login

3. Thoughts

Although it is a bit disgusting to combine it with iframe, it can realize our idea

In the implementation of this function, we use the broadcast and monitoring of the bus event bus

  1. In fact, we can think about this carefully, because the large-scale use of broadcasts is uncontrollable. We can completely use vuex to achieve this. Using broadcasts is indeed lazy

  2. Broadcasting is not not recommended, but it must be used in the right scenario. In fact, using broadcasting is not very good and is not conducive to expansion. Who can guess what expansions there will be?

You don’t need to care about the specific code. If you encounter similar problems, just understand this idea.

The above is what I compiled for everyone. I hope that I will use it in the future. Helpful to everyone.

Related articles:

How to call vuex to store interface data in vue.js

How to implement a number matching game using javascript

The process of encapsulating and submitting data in the form

The above is the detailed content of How to implement integrated Iframe page using Vue. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template