V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
avenger
V2EX  ›  Vue.js

请教一个 Vue.js 动态加载外部 html 的事件处理问题

  •  
  •   avenger ·
    bolechen · 2019-04-09 23:22:27 +08:00 · 4342 次点击
    这是一个创建于 2084 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求是这样的

    Vue 单页 app,app 首页用户需要自定义,内容是后台用户编辑的,前端通过 api 来获取用户后台编辑的内容,api 返回 html 格式。

    现在需要在前端输出 html 的时候,处理 html 中的所有链接,捕获默认的点击事件,转换成 Vue-route 的本地事件,跳到对应的路由页面。

    网上已经找到一位老哥的代码了( https://dennisreimann.de/articles/delegating-html-links-to-vue-router.html ),思路如下:

        <div
          class="imgs content"
          v-html="app.home"
        />
    
    mounted () {
      window.addEventListener('click', event => {
        const { target } = event
        // handle only links that do not reference external resources
        if (target && target.matches("a:not([href*='://'])") && target.href) {
          // some sanity checks taken from vue-router:
          // https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L106
          const { altKey, ctrlKey, metaKey, shiftKey, button, defaultPrevented } = event
          // don't handle with control keys
          if (metaKey || altKey || ctrlKey || shiftKey) return
          // don't handle when preventDefault called
          if (defaultPrevented) return
          // don't handle right clicks
          if (button !== undefined && button !== 0) return
          // don't handle if `target="_blank"`
          if (target && target.getAttribute) {
            const linkTarget = target.getAttribute('target')
            if (/\b_blank\b/i.test(linkTarget)) return
          }
          // don't handle same page links/anchors
          const url = new URL(target.href)
          const to = url.pathname
          if (window.location.pathname !== to && event.preventDefault) {
            event.preventDefault()
            this.$router.push(to)
          }
        }
      })
    }
    

    本地调试的时候发现一个问题,api 返回的 html 是类似这样的

    <a href="/xxx">
      <img src="/bbb">
    </a>
    

    在上例中,我在事件开始输出 log,获取到的一直是 img 标签,而不是 a 标签,这也导致上面后续逻辑无法执行。

    mounted () {
      window.addEventListener('click', event => {
        const { target } = event
        console.log(target)
    

    看起来不是一个大问题,浪费了一晚上时间还没有解决。:( 我承认前端我接触太少,js 基础功力还要加强,希望有这方面经验的大佬给一些指点,定重谢!

    7 条回复    2019-04-13 11:12:49 +08:00
    murmur
        1
    murmur  
       2019-04-09 23:29:44 +08:00   ❤️ 1
    大概意思懂了 只是我感觉难点在你的编辑器上 支持自定义链接的可视化编辑器很多 但是支持输入路由的编辑器还没见过
    如果你能解决这一点 后面的处理就很随意了
    这个例子的写法很明显是个冒泡捕获 你知道有一个 closest 你可以用这个函数找到触发事件最近的一个父级 a 标签
    0044200420
        2
    0044200420  
       2019-04-09 23:29:57 +08:00   ❤️ 1
    avenger
        3
    avenger  
    OP
       2019-04-09 23:40:40 +08:00
    @murmur 感谢,初衷是后台直接输入 http 链接,前端再根据链接转换成 vue 用的路由
    avenger
        4
    avenger  
    OP
       2019-04-09 23:41:07 +08:00
    @0044200420 感谢,看了一下午冒泡了…… 还是没搞懂 :(
    randyo
        5
    randyo  
       2019-04-09 23:42:14 +08:00 via Android   ❤️ 1
    判断一下 target 是不是 a 标签,不是的话判断他的 parentElement 是不是,不是的话重复上一步
    a62527776a
        6
    a62527776a  
       2019-04-10 00:05:07 +08:00 via Android
    你用带渲染器的 vue 然后把 html 片段转换成你要的 vue template 再用 render 函数包裹起来执行一下就行了
    avenger
        7
    avenger  
    OP
       2019-04-13 11:12:49 +08:00
    解决了,过来填个坑

    ```
    onPageClick(event) {
    let { target } = event
    while (target && target.tagName !== 'A') target = target.parentNode;
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1110 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:36 · PVG 07:36 · LAX 15:36 · JFK 18:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.