Element-Inject/Provide调用组件中的方法

Element-Inject/Provide调用组件中的方法

问题背景

在做一个前端多语言切换的效果时, 遇到一个问题. 就是系统菜单是后端提供的, 前端给一个语言字段, 后端做过滤,显示对应语言的菜单
这个时候前端切换语言时, ElementUI组件能自动切换成相应语言(引入i18n插件) 但是系统的菜单栏就必须要刷新页面才能更新成对应语言的菜单(可以直接ctrl+r 或者 window.location.reload(),太瓜皮了这样)

然后找到了一个方式, 就是通过inject/provide的方式可以在组件中调用另外一个组件中的方法. 不过那个例子上写的是在router-view上做的v-if, 我这里的场景只是单纯想在一个组件里调另外一个组件的方法(当然也可以使用this.$refs.refName.function(), 但是这个是要父子组件才能行). 然后实验了一下发现居然在其他组件里也能用, 所以就先记下来

解决方式

定义两个组件A 以及 组件B, 组件A中一个change事件想要触发组件B中的 function b(){} 此时可以直接在A组件中inject注入B组件provide的方法
参考地址: https://blog.csdn.net/weixin_43878117/article/details/114820914

  1. provide方法
<template>
  <layout>
    <side-menu slot="side" v-if="isRouterAlive"></side-menu>
    <main-header slot="header"></main-header>
    <div slot="main">
      <transition name="fade" mode="out-in">
        <router-view></router-view>
      </transition>
    </div>
  </layout>
</template>

<script>
export default {
	provide(){
		return {
			reload: this.reload
		}
	},
  components: {
    // 布局
    Layout: () => import("@/components/layout/Layout.vue"),
    // 左侧菜单
    SideMenu: () => import("@/components/layout/SideMenu.vue"),
    // 头部
    MainHeader: () => import("@/components/layout/Header.vue")
  },
  data(){
	  return {
		  isRouterAlive: true
	  }
  },
  methods:{
	  reload(){
		  this.isRouterAlive = false;
		  this.$nextTick(()=>{
			  this.isRouterAlive = true;
		  })
	  }
  }
};
</script>

此处通过v-if能够控制side-menu组件去重新加载一次DOM, 然后再method中顶一个一个方法reload(), 再把定义的reload()方法provide出去

  1. 然后在要调用reload()方法的组件中注入inject刚刚provide出的方法

<template>
	<el-row type="flex" class="header" justify="space-between">
		<el-col :span="10" class="header-left">
			<div class="header-left-logo">
				<a href="javascript:void(0)" class="logo">
					<img src="@/assets/layout/head_logo_black.png" width="43px" height="29px" />
				</a>
			</div>
		</el-col>
		<el-col :span="14" class="header-right">
			<div class="welcome-title">
				<a href="../../../book/index.html" class="help" target="_blank"
					><i class="el-icon-question">{{ $t("header.guideBook") }}</i></a
				>
				<img src="@/assets/layout/home_4_1@2x.png" width="40px" height="40px" />
				{{ $t("header.welcome") }}
				<span class="user">{{ user }}</span
				>&nbsp;&nbsp;| &nbsp;&nbsp;
				<a href="/" @click="logout" underline="false">{{ $t("header.exit") }}&nbsp;</a>

				<el-dropdown @command="handleCommand" style="margin-left: 10px">
					<span class="el-dropdown-link">
						{{ lang }}<i class="el-icon-arrow-down el-icon--right"></i>
					</span>
					<el-dropdown-menu slot="dropdown">
						<el-dropdown-item
							v-for="(item, index) in languageList"
							:key="index"
							:command="item.code"
							>{{ item.name }}</el-dropdown-item
						>
					</el-dropdown-menu>
				</el-dropdown>
			</div>
		</el-col>
	</el-row>
</template>

<script>
export default {
	inject: ['reload'],
	data() {
		return {
			value: "",
			lang: "English",
			headerTitle: "Midea"
		};
	},
	methods: {
		handleCommand(command) {
			this.reload();
			this.languageList.forEach(item => {
				if (item.code === command) {
					this.lang = item.name;
					if (command === "ja") {
						this.$i18n.locale = "ja";
					} else if (command === "zh-Hans" || command === "zh-Hant") {
						this.$i18n.locale = "zh";
					} else {
						this.$i18n.locale = "en";
					}
					localStorage.setItem("lang", item.code);
					return;
				}
			});
		},
	}
};
</script>

inject之后可以直接在当前组件中调用provide出的方法

延伸

  1. 此方法适用于调用没有引入的组件中的方法
  2. 这样控制组件显示隐藏可以不用整个页面去刷新
posted @ 2022-05-30 19:03  你啊347  阅读(220)  评论(0编辑  收藏  举报