V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
exc
V2EX  ›  问与答

在 vue 里,如何把变量(props)自动传递下去?

  •  
  •   exc · 2021-03-10 22:16:47 +08:00 · 1286 次点击
    这是一个创建于 1114 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个需求,做 i18n 国际化,网上看的诸多方案不太喜欢(都要在模板里调用一个翻译函数),于是捣鼓了一种方式:

    让 vue app 实例持有一份 i18n 清单,并通过 props 传递给每个实例或组件,这样每个实例都能使用这个 i18n 对象了。

    不过这种写法还是比较丑陋的,因为传递的方式是这样的,且每个地方都要写一遍:

    <router-view v-bind:i18n="i18n" class="view"></router-view>
    

    必须要显式的把 i18n 传递给 router-view,我希望这一步能够自动完成,即写的时候不用写 v-bind:i18n="i18n"

    <router-view class="view"></router-view>
    

    不知道 vue 支持不支持这种操作,怎么做?

    题外话,vue 有没有一种方式,让组件访问上级实例的数据?就是说我不把 i18n 通过 props 传递给组件,组件(模板)也能访问 i18n,如果可以这样,那么更好了,可以少写很多代码。

    第 1 条附言  ·  2021-03-10 23:05:33 +08:00
    经楼下提示,使用 provide / inject 可以向所有下级组件注入数据,但如何修改 provide 的数据呢?下面链接是一个测试(点击 T 按钮切换语言),使用 props 的组件可以正常工作,使用 provide/inject 的则不能。

    https://jsfiddle.net/Lzab481n/4/
    第 2 条附言  ·  2021-03-11 10:07:15 +08:00
    谢谢大家的回复,#11 @noe132 给的答案已经解决了我的问题,参考 demo: https://jsfiddle.net/mLohkr94/5/
    第 3 条附言  ·  2021-03-11 18:25:48 +08:00
    经试验,感觉插件更符合我的需求,也更简洁,代码如下: https://jsfiddle.net/72mh01ry/

    可以和上一个 append 对比,感谢 @xingyue @learningman
    18 条回复    2021-03-11 13:42:22 +08:00
    xingyue
        1
    xingyue  
       2021-03-10 22:28:06 +08:00 via Android   ❤️ 1
    看需求 mixin 应该很符合
    https://cn.vuejs.org/v2/guide/mixins.html

    不过个人建议还是插件
    https://cn.vuejs.org/v2/guide/plugins.html
    kikyous
        2
    kikyous  
       2021-03-10 22:29:37 +08:00 via Android   ❤️ 2
    inject/provider
    szdubinbin
        3
    szdubinbin  
       2021-03-10 22:31:11 +08:00   ❤️ 1
    感觉你的描述很像 “inject”这个特征,
    https://cn.vuejs.org/v2/api/#provide-inject

    「这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。」
    exc
        4
    exc  
    OP
       2021-03-10 22:34:55 +08:00
    @xingyue @kikyous @szdubinbin 感谢,这就去看看
    Shook
        5
    Shook  
       2021-03-10 22:44:49 +08:00
    i18n.js:
    ```
    import { inject } from 'vue';

    function i18n() {
    console.log('hello');
    }

    const globalKey = 'i18n';

    export function install(app) {
    app.provide(globalKey, i18n);
    }
    export function useI18n() {
    return inject(globalKey);
    }

    export default { install };
    ```

    main.js:
    ```
    import { createApp } from 'vue';
    import App from './app.jsx';
    const app = createApp(App);

    import i18n from 'i18n.js';
    app.use(i18n);

    app.mount('#app');
    ```

    Child:
    ```
    import { useI18n } from 'xxx';
    export {
    setup() {
    const i18n = useI18n();
    i18n(); // hello

    return {
    i18n,
    };
    }
    };
    ```
    exc
        6
    exc  
    OP
       2021-03-10 23:02:55 +08:00
    @kikyous @szdubinbin inject/provider 可以免去在模板里申明一次的麻烦,但如何修改 provider 的数据呢?
    cgpiao
        7
    cgpiao  
       2021-03-10 23:31:38 +08:00 via iPhone
    emit 事件
    exc
        8
    exc  
    OP
       2021-03-10 23:38:59 +08:00
    @xingyue mixin 在实例里更新数据后,组件不会响应,请问怎么办呢?测试如下: https://jsfiddle.net/Lzab481n/5/

    点击 T 按钮后,`text-names` 组件不会响应
    noe132
        9
    noe132  
       2021-03-10 23:55:55 +08:00
    你 text-names 又没有 inject i18n,怎么可能会有响应
    你 mixin 进来一个永远不会变的 getter,和你的 inject 一点关系都没有。
    exc
        10
    exc  
    OP
       2021-03-11 00:01:59 +08:00
    @noe132 那应该怎么写呢?
    noe132
        11
    noe132  
       2021-03-11 00:14:00 +08:00   ❤️ 1
    provide 默认不是 reactive 的,所以需要 provide 一个 reactive 的对象
    所有需要用到的地方写 inject
    https://vuejs.org/v2/api/#provide-inject
    https://jsfiddle.net/mLohkr94/5/
    learningman
        12
    learningman  
       2021-03-11 00:14:44 +08:00 via Android
    写个插件吧,官方的插件教程就是 i18n
    zqx
        13
    zqx  
       2021-03-11 07:06:21 +08:00 via Android
    直接在 main.js 的 vue 原型上注入吧
    这样每个 vue 实例都可以通过 this.i18n 访问到你注入的数据
    exc
        14
    exc  
    OP
       2021-03-11 10:05:16 +08:00
    @learningman 有链接吗,官方网站上没找到。。。
    learningman
        15
    learningman  
       2021-03-11 10:21:34 +08:00 via Android
    @exc https://cn.vuejs.org/v2/guide/plugins.html
    老哥,官方教程啊。。。
    exc
        16
    exc  
    OP
       2021-03-11 12:09:24 +08:00
    @learningman 官方的插件教程就是 i18n 。那个,这个,没看到 i18n 的示例呀,就几行代码,连一个完整的 demo 都没有。
    exc
        18
    exc  
    OP
       2021-03-11 13:42:22 +08:00
    @learningman 非常感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5403 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:56 · PVG 14:56 · LAX 23:56 · JFK 02:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.