Skip to content

Dynamic content in Vue components #1074

Closed

Description

@Fohlen

Bug Report

In the documentation it says that one can embed Vue instances. I tried building an interactive component for our documentation like so:

# Servers

Thanks to [AngrySnout](https://github.com/AngrySnout/SauerTracker) we have excellent statistics for the game.

<div id="server">
    <ul>
        <li v-for="server in servers" :key="server.description"> {{ server.descriptionStyled }} </li>
    </ul>
</div>

<script>
  const API_URL = "https://tomaten.sauertracker.net/api/servers"

  new Vue({
    el: '#server',
    data: () => ({
        servers: []
    }),
    async mounted {}
        console.log("HEY")
        const response = await fetch(API_URL);
        this.servers = await response.json(); 
    }
  })
</script>

However when loading the page the content quickly flashes before getting "rendered away".
I have no idea what sorcery is going on behind the scenes but my best bet is that it's an unsupported feature.

Steps to reproduce

(see above)

What is current behaviour

(see above)

What is the expected behaviour

The app that is rendered on screen should allow for dynamic content.

Other relevant information

  • Bug does still occur when all/other plugins are disabled?

  • Your OS: OSX 10.15.3 (19D76)

  • Browser version: Version 80.0.3987.132 (Official Build) (64-bit)

  • Docsify version: 4.11.2

  • Docsify plugins: search plugin

Activity

  1. anikethsaha commented on Mar 14, 2020

    @anikethsaha
    Member

    Sorry I am not familiar with vue so cant really help you here !

    Feel Free to investigate and submit the fix.

    Also, try testing with older version and check in which it broke, it will help in investigation

  2. Koooooo-7 commented on Mar 15, 2020

    @Koooooo-7
    Member

    Actually ,It seems some issues about the Vue supports in docsify.
    Currently, when u create ur own Vue instance, you will not get the Vue instance in the mounted hook by using this (this directs to the window obj in docsify now).

    the Vue instance was covered in this.__EXECUTE_RESULT__.
    there is showing how we execute script in docsify.

      // Execute script
      if (
        this.config.executeScript !== false &&
        typeof window.Vue !== 'undefined' &&
        !executeScript()
      ) {
        setTimeout(_ => {
          const vueVM = window.__EXECUTE_RESULT__;
          vueVM && vueVM.$destroy && vueVM.$destroy();
          window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main');
        }, 0);
      } else {
        this.config.executeScript && executeScript();
      }

    Although, I tried to set the root data in a hack way, it seems not work.
    I haven't found a way to resolve it yet, I hope those informations could be helpful.

  3. stale commented on May 14, 2020

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

  4. trusktr commented on Jun 21, 2020

    @trusktr
    Member

    stale bot may make it harder to triage issues if they get closed before we see them. Wdyt?

    Now that I've realized this, I need to go check all the closed issues.

  5. trusktr commented on Jun 21, 2020

    @trusktr
    Member

    Regarding the original issue, I think I encountered them. I believe it has to do with double execution of scripts, and I refactored this code in my personal fork. I will make a PR soon...

  6. jhildenbiddle commented on Jul 5, 2020

    @jhildenbiddle
    Member

    @Fohlen --

    This bug is currently being addressed in #1271. The changes in that PR allow your example to work as expected, albeit with a few minor changes:

    <div id="server">
      <ul>
        <li v-for="server in servers" :key="server.description">
          <span v-html="server.descriptionStyled"></span>
        </li>
      </ul>
    </div>
    
    <script>
      const API_URL = "https://tomaten.sauertracker.net/api/servers"
    
      new Vue({
        el: '#server',
        data: () => ({
          servers: []
        }),
        async mounted() {
          console.log("HEY")
          const response = await fetch(API_URL);
          this.servers = await response.json();
        }
      });
    </script>
  7. linked a pull request that will close this issueFix Vue Reactivity #1271on Jul 5, 2020
  8. woshiguabi commented on Aug 14, 2020

    @woshiguabi
    Contributor

    my solution:
    set executeScript to false and use a plugin to initial Vue instance

    ((global, plugin) => {
      global.DocsifyVuePlugin = plugin;
    })(window, () => (hook) => {
      let script = null;
      hook.beforeEach(() => {
        if(window.__DOCSIFY_VUE_INSTANCE__ ){
          window.__DOCSIFY_VUE_INSTANCE__.$destroy();
          window.__DOCSIFY_VUE_INSTANCE__ = null;
        }
      });
      hook.afterEach((content, next) => {
        script = null;
        const template = content.replace(/<script>([\s\S]*?)<\/script>/g, ($0, $1) => {
          if(!script) {
            script = $1;
          }
          return '';
        });
        return next(script ? `<div id="docsifyVuePluginInstance">${template}</div>` : content);
      });
      hook.doneEach(() => {
        if(!script) return;
        const vm = window.eval(script);
        script = null;
        if (vm instanceof window.Vue) {
          vm.$mount('#docsifyVuePluginInstance');
          window.__DOCSIFY_VUE_INSTANCE__ = vm;
        }
      })
    });
    <div>{{msg}}</div>
    <script>
    new Vue({
      data() {
        return { msg: 'hello' };
      },
    });
    </script>
  9. jhildenbiddle commented on Oct 8, 2020

    @jhildenbiddle
    Member

    @Fohlen --

    Fixed in #1271. The example code you provided has a few issues though. Here's update code that will work as is:

    # Servers
    
    Thanks to [AngrySnout](https://github.com/AngrySnout/SauerTracker) we have excellent statistics for the game.
    
    <div id="server">
        <ul>
            <li v-for="server in servers" :key="server.description"><span v-html="server.descriptionStyled"></span></li>
        </ul>
    </div>
    
    <script>
      const API_URL = "https://tomaten.sauertracker.net/api/servers"
    
      new Vue({
        el: '#server',
        data: () => ({
            servers: []
        }),
        mounted() {
          console.log("HEY")
          fetch(API_URL)
            .then(response => response.json())
            .then(data => this.servers = data)
            .catch(err => console.log(err));
        }
      })
    </script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugconfirmed as a bugvuejsrelated to Vue.js

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions