1. uniapp中this.$refs的问题
uniapp是一款跨平台开发框架,可以同时开发iOS、Android、H5等多个平台的应用。而在开发过程中,我们经常需要用到this.$refs来获取组件的实例或者操作组件的DOM元素。然而,在uniapp中使用this.$refs却会出现一些问题。
1.1 this.$refs在uniapp中的表现
在vue.js中,我们可以使用this.$refs获取组件的实例或者DOM元素。但是,在uniapp中,this.$refs并不能像在vue.js中一样正常使用。
在uniapp中,当我们使用this.$refs.xxx获取子组件实例时,控制台会报错:
Cannot read property '$vm' of undefined
这是因为uniapp并不支持使用this.$refs来获取子组件实例。
1.2 this.$refs无法使用的原因
我们已经知道,uniapp中不能使用this.$refs来获取子组件实例。那么,这是为什么呢?原因主要有两点:
uniapp是基于webview的跨平台框架,而webview不支持使用this.$refs获取子组件实例。
uniapp中使用了类似mpvue的编译器,代替了vue.js中的编译器。这个编译器会在编译期间把模板编译为小程序代码,这就会造成this.$refs无法使用。因为小程序中,使用this.$refs来获取组件实例是不被支持的。
2. 替代方案
既然在uniapp中使用this.$refs会出现问题,那么我们就需要寻找替代方案来获取组件实例或者操作DOM元素。
2.1 获取组件实例
在uniapp中,获取组件实例有两种方法:
2.1.1 使用this.getRef(node)
uniapp提供了一个getRef(node)方法,可以用来获取组件实例。这个方法会返回组件的实例对象,我们可以通过这个实例对象来操作组件:
// 获取子组件实例
let subComponent = this.getRef('subComponent');
// 调用子组件方法
subComponent.xxx();
// 获取子组件属性
let propValue = subComponent.propName;
需要注意的是,这种方法只能获取通过ref命名的组件,无法获取通过v-for渲染的组件。
2.1.2 使用provide/inject
provide/inject是vue.js中的一种属性注入方式,uniapp也支持这种方式来获取组件实例。我们可以在父组件中通过provide方法提供组件实例,在子组件中通过inject方法来获取组件实例:
// 父组件中提供组件实例
provide () {
return {
mainComponent: this
};
},
// 子组件中获取组件实例
inject: ['mainComponent'],
mounted () {
// 调用父组件方法
this.mainComponent.xxx();
}
需要注意的是,使用provide/inject时,组件的实例只能在组件的生命周期钩子函数中获取,不能在组件中的methods、computed等属性中使用。
2.2 操作DOM元素
在uniapp中,操作DOM元素有两种方法:
2.2.1 使用selectComponent方法
在uniapp中,我们可以使用selectComponent方法来获取DOM元素:
// 获取组件中的DOM元素
let domNode = uni.createSelectorQuery().in(this).select("#domId");
需要注意的是,这个方法只能用来获取组件中的DOM元素,无法获取Vue实例中的DOM元素。
2.2.2 使用uni.$on和uni.$emit方法
在uniapp中,除了使用selectComponent方法来获取DOM元素外,我们还可以使用uni.$on和uni.$emit方法来更新DOM元素。比如:
// 在父组件中监听子组件事件
uni.$on('event', (eventVal) => {
this.dataValue = eventVal;
});
// 在子组件中触发事件
uni.$emit('event', 'eventValue');
这种方法可以用来更新Vue实例中的DOM元素。
3. 总结
在uniapp中,this.$refs不能像在vue.js中一样正常使用。但是,我们可以使用其他方式来获取组件实例和操作DOM元素。其中,getRef和provide/inject是获取组件实例的两种方式;selectComponent和uni.$on/uni.$emit是操作DOM元素的两种方式。我们需要根据具体的情况来选择使用哪种方法。