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

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

  •  
  •   avenger · 98 天前 · 915 次点击
    这是一个创建于 98 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求是这样的

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

    ```
    onPageClick(event) {
    let { target } = event
    while (target && target.tagName !== 'A') target = target.parentNode;
    ```
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3301 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 20ms · UTC 04:38 · PVG 12:38 · LAX 21:38 · JFK 00:38
    ♥ Do have faith in what you're doing.