vue中变量与函数作用域的问题?

我的vue项目中设置了两个路径,当路径为a时渲染A组件,当路径为b时渲染B组件。两个组件都需要可以访问并修改x变量。因此必须设置全局变量x和修改x变量的全局函数changeX。
因为项目比较小,我没有使用vuex,在网上搜了一下大家好像都是在Vue.prototype来定义全局函数,如何定义全局变量我没有找到。
无意中,我发现可以在根目录的index.html里,在<script src="/dist/build.js"></script>(这是经过webpack打包后引入的文件)之前再放插入一个<script>标签,标签内声明的变量和函数可以在任意组件中访问。像下面这样

//index.html
<body>
    <div id="app">
        <router-view></router-view>
    </div>
    <script>
      //定义全局变量与全局函数,在任意组件中都能访问与使用。

      let x 

      function changeX () {
      //对x进行操作
      }
    </script>
    <script src="/dist/build.js"></script>
  </body>

在上面这种情况下,A组件和B组件中均可调用changeX函数,如:

//B.vue
<script>
export default {
    methods:{
        aaa:function(){
            changeX()
        }
    }
}
</script>

上面这样是可行的,但是当全局函数和全局变量很多的时候放在index.html会很难看,于是我就写专门写了一个global.js文件,把x和changeX放到里面,然后用<script>标签引到index.html中,如下:

//index.html
<body>
    <div id="app">
        <router-view></router-view>
    </div>
    <script src="./src/global.js"></script> //里面放x和changeX
    <script src="/dist/build.js"></script>
</body>

这时再运行,控制台报错:“changeX不是一个函数”。

把同样的js代码从文件中引过来和直接放在<script>标签中出现了不一样的效果,这是为什么呢?

另外一个问题,main.js是webpack的入口,我们在里面引入组件,定义Vue实例,我直接在这个文件里定义变量和函数,在组件中也是不能访问的,如下:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

let x    //在组件中无法访问

function changeX () {...}   //在组件中无法访问  

import A from './components/A.vue';
import B from './components/B.vue';


let routes = [
    {path:'/', component: A},
    {path:'/:id', name:'user',component: B}
];

let router = new VueRouter({
    mode: 'history',
    routes
})

new Vue({
    router,
  el: '#app'
})

我实在被作用域的问题给搞迷糊了,现在只能把全局的东西都写在index.html中,有懂的前辈希望指点一下。

阅读 6.9k
3 个回答

于是我就写专门写了一个global.js文件,把x和changeX放到里面

既然楼主写了个global.js文件,就可以考虑遵循模块化的概念,使用import在各个组件中引用

下面从利于楼主理解的角度来说明,可能会存在一些不严谨的地方:

关于作用域问题,简单来说,你访问不到不是因为作用域不正确,而是打包工具通过修改变量名,包裹函数,等等多种方法帮你做到了隔离作用域,这样做的好处就是为了保证每个组件,每个模块都是相对独立的.

楼主如果感兴趣可以看看编译之后的代码,webpack之类的打包工具会讲每一个模块,包括入口文件(入口文件也被认为是一个模块)包裹成一个函数,函数返回值导出引用,所以不论你变量怎么写,看似作用域在window下,实际上已经被包裹进了函数中,这也是遵循了ES6_module或者commonjs模块的规范

推荐楼主使用import去引用global.js

如果楼主一定想要按上面的方法来实现,可以考虑把全局变量和方法挂载在window下,比如 window.xxx

因为没有放出global.js文件,但是我猜测一下,你global文件输出文件时是不是使用了es6的export输出的变量,浏览器还是不支持这种写法的,你如果想输出一个变量,直接用最普通的写法

 <script>
      //定义全局变量与全局函数,在任意组件中都能访问与使用。

      let x 

      function changeX () {
      //对x进行操作
      }
 </script>

把script标签中写道global中,通过script标签引入就会成为全局变量

新手上路,请多包涵

是不是要拿vue的实例去获取呢 因为在vue中的数据或者是属性 都可以在vue的实例中获得的 好像

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题