#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用 原创 精华

阿毛0920
发布于 2022-7-29 17:41
浏览
3收藏

本文正在参加星光计划3.0–夏日挑战赛

前言

上回我们讲过几个危险的方法,所以,现在拿来单独讲一讲,不过这几个方法配合起来玩还是挺有意思的,理论上,你可以通过这几个方法,在任意一个组件操作所有的界面,是不是很棒?是不是很腻害?(ps:如果你真得用这种方式开发,可能出问题的时候,需要你和代码有一个能跑就行)-|·_·|——

获取VM实例方法

页面结构

#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
每个节点就是一个页面组件,每个节点就是一个vm实例

VM实例是怎么样的?

我们将它遍历输出的结果如下图,
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
从上面的图中,我们可以看出,有很多熟悉的VM实例方法和属性还有自定义的方法

入口文件是啥?

#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
如上图,在预览器中的entry的路径,此时我们的入口文件为test2,如果想切换入口文件,就去文件目录选择想要切换成入口文件的文件,然后点击预览器中的刷新按钮,即可切换

$root

用法 this.$root() 无参数
获取根VM实例,这跟根vm实例和选择的入口文件有关。例如,上图页面结构图,我们选择得入口文件test2页面,在test2页面test3组件分别输出他们的$root中的data数据
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
从上图中我们可以看出,当前页面就是入口文件时也就是最顶级VM实例时,获取到的$root就是当前的VM实例,当在任意一个组件中获取$root时都可以拿到当前的根实例。
当然我们的入口文件改成test1时,得到的结果如下图
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

$parent

用法this.$parent() 无参数
获取父组件的VM实例,当前组件为入口文件时也就是最顶级VM实例,使用this.$parent(),就会得到以下结果,基本都是内部的的属性,例如在test1组件获取this.$parent
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
我们分别在test2和test3组件获取他的$parent, VM实例的data结果如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

$child

用法this.$child("需要获取的自定义子组件的ID值") 有参数 id
获取自定义的组件的VM实例,需要给导入的自定义组件设置id属性,我们分别在test1和test2获取自定义组件test2和test3组件

<!-- 当前组件,test1组件 -->
 <div style="width: 100%;height: 40%;"  >
        <test2 id="r" num="{{num}}">
        </test2>
    </div>
<!-- 当前组件,test2组件 -->
<div class="container" @click="dd" id="gg"  >
    <test3 ref="test3" id='ww'>
    </test3>

</div>

分别使用this.$child('r').__datathis.$child('ww').__data得到的结果如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

VM实例的使用

正常的组件通信

一般我们开发时,组件之间的通信是有迹可循的,也是符合逻辑的,通信图如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

使用VM实例通信,乃至操作

但是,一旦我们开发时组件之间的通信或者跨组件操作,使用通过VM实例的话,那将会对后期维护很麻烦,甚至出BUG你都找破头,你永远不知道会在那个组件突然冒出来操作一下其他组件,如下图
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
上面这个图才一共五个节点,就已经这么乱了,如果几十上百个,估计得炸,所以,这种玩法只适合自己写的一些小项目或者遇到一些没法解决的问题,迫不得已才使用。

或许还可以这样玩

每个节点都可通过一个中心调度器,在中心调度器中对所有的组件进行统一操作,en…感觉…反正也就是个想法,谁有空可以玩玩
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

VM实例的跨组件操作

接下来,我们将在test3组件操作test5组件
具体流程 test3 → test1 → test4 → test5
在引用test4和test5时,我们分别给他们设置了id为test4,test5

//test5 组件
export default {
    data: {
        title: "我是test5"
    },
    useing(s){
        console.log(`${this.title},${s}正在使用我的useing方法 `)
    }
}
// test3组件
  onLayoutReady(){
        const node = this.$root().$child('test4').$child("test5")
        node.useing("test3")
        console.log(`原test5的title值 ${node.__data.title}`)
        node.__data.title= '我被修改了'
        console.log(`改后的test5的title值, ${node.__data.title}`);

    },

输出的结果如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
用起来感觉如何,写到这里,就想起前面dom上说过自定义的组件事件阻塞没有效果,我们也可以利用vm实例来解决

阻止事件冒泡

起因

由于dom中有一个事件冒泡机制,如下图,子组件test3触发click事件,那么,其父组件test2,以及test2的父组件test1也同样因为事件冒泡触发click事件
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区

stopPropagation() 和 currentTarget 结果不符合预期

在上次写到的stopPropagation()应该是用来阻止事件冒泡的方法,但是并无效果,使用后还是继续冒泡,不知道你们的设备上是不是这样,我在预览器上就这样,没有板子测试,currentTarget也不符合预期效果,没有办法获取事件源的dom,也无法就处理事件冒泡,那么冒泡该如何绕开

通过移除事件和添加事件

在同一个页面组件下的父子元素事件冒泡

<div class="container" @click="dd" id="gg"  >
    <div id="e" ref="test2" style="height: 222px; height:300px ;background-color: aqua;"  @click="c">
      <text class="title" >
          {{title}}, test1的子组件
            test1传过来的num
        </text>
    </div>
   
</div>
   dd(e){
        console.log("父元素click事件触发")
    },
    c(e){
      console.log('子点击')

    },

#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
我们可以通过dom的方法 removeEventaddEvent

   dd(e){
        console.log("父元素click事件触发")
    },
    c(e){
      console.log('子点击')
      const d = this.dd
      const node =    this.$element('gg');
      node.removeEvent('click')

        setTimeout(()=>{
            node.addEvent('click',d)
        })

    },

#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
通过这样移除事件回调函数后再添加,我们可以模拟一个类似于一个阻塞事件冒泡,但是还是会继续冒泡,那么子组件冒泡到父组件又怎么解决?

处理跨组件冒泡

上面我们提到的VM实例操作终于有用了,我们可以通过获取到父组件注册的事件回调方法,然后去取消父组件的
我们给test1组件设置一个id = “test1” ,click事件回调函数为cc

<div class="container" id="test1" @click="cc" data-bb="{{title1}}}"  >
    <div style="width: 100%;height: 10%; display: flex; flex-direction: column;"  >
        <text class="title"   >
            这是父组件{{title}}
        </text>

    </div>
  
</div>

在父组件test1的click事件回调方法

 cc(e){
     console.log('我是test1,click事件触发的方法,cc')
    },

test2组件click事件的回调函数

   c(e){
      console.log('子点击')
      const d = this.dd
      const node =    this.$element('gg');
      node.removeEvent('click')

        setTimeout(()=>{
            node.addEvent('click',d)
        })

    },

事件冒泡的结果图如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
处理跨组件事件冒泡
我们可以通过获取vm实例,再通过获取触发click事件的元素,然后移除和添加事件

  c(e){
      console.log('子点击')
     const node =    this.$parent();

     const fun = node.cc;
     const dom = node.$element('test1')
      dom.removeEvent('click')

        setTimeout(()=>{
            dom.addEvent('click',fun)
        })

    }

结果如下
#夏日挑战赛# OpenHarmony基于JS开发的VM实例的一点应用-鸿蒙开发者社区
这样子可以避免触发父组件的点击事件

最后

获取VM实例的这几个方法还是老规矩,不推荐使用,平时玩玩还可以,上述的事件冒泡的处理也莫得办法,官方给的api接口我用竟然没效果,不知道你们用的是咋样

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2022-7-29 17:41:14修改
10
收藏 3
回复
举报
2条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

这是我学过的最复杂的冒泡,VM既然如此复杂,他的具体应用场景是哪里呢?

回复
2022-7-29 19:36:03
阿毛0920
阿毛0920 回复了 红叶亦知秋
这是我学过的最复杂的冒泡,VM既然如此复杂,他的具体应用场景是哪里呢?

可能最多是组件通信,但就是因为复杂,他可以用更加友好的方式被替代,有的时候想绕过一些东西的时候也可以使用

1
回复
2022-7-29 19:56:08
回复
    相关推荐