这个问题我看github上面有人也提了类似的 issue 但是好像没有说明具体原因出来?https://github.com/vuejs/vue/...
具体场景
我在一个头文件里面定义了一个方法 例如
var ms = {
open:function(url){
//伪代码
}
}
在具体页面我把这个文件引入在头部
这是业务代码
<div id='app'>
<button @click='ms.open('./home/)'>按钮1</button>
<button onclick='ms.open('./home/)'>按钮2</button>
</div>
<script>
var app = new Vue({
el:#app,
data:{
}
})
</script>
问题来了,不管我点的是按钮1还是按钮2,都显示ms未定义?请问各位大佬,这是什么原因?针对这样的场景有没有好的解决办法?
总结:vue.min.js 不知出于何种原因,没有设置
_renderProxy
为hasProxy
,导致with
语句会正确执行原本的语义。打了断点找了一通,找到原因了:
本质上就是
with
的问题。先来看 vue.js 中设置渲染代理的地方:
可以看到,当浏览器中
Proxy
存在且为原生对象时会设置vm._renderProxy
为某个代理,在我们的例子中将设置hasHandler
代理,后面会看到。而 vue 渲染一个节点元素使用的代码如下:
其中
ref.render
即模板被编译后的渲染函数:可以看到,此时渲染函数中的
this
将会被指向vm._renderProxy
代理,而代理的响应函数为:注意到代理挂载的是
has
拦截,因此当with(vm._renderProxy) {... ms ...}
时,会调用此时不满足
has
函数中所设置的一系列条件,所以会报错。而在 min 版本下,我不清楚为何设置
vm._renderProxy
的代码没了,只有在_init
函数中简单的n._renderProxy = n
,即在 min 下不会上面说的代理。既然不走代理,那么
此时由于
_renderProxy
没有设置为hasProxy
,那么with
会简单得尝试在_renderProxy
上寻找ms
,找不到的时候会向上寻找一直到window
作用域,此时即找到。只有注册在 vue 内的方法才能被 vue 调用,因为模板会被重新编译为 vue 作用域(具体来说应该是某个组件)内的渲染函数。
你的
ms
既不是 vue (组件)的data
,也不是computed
,更不是methods
,vue 上哪儿找ms
去。