简体   繁体   中英

Async data in Vue.js filter

I have a filter to convert content with id into user name. For instance, it converts Thank you @id-3124324 ! into Thank you @Jack ! .

var filter = function (content) {
    var re = /\s@(id\-\d+)\s/g;
    var matches = [];
    var lastMatch = re.exec(content);
    while (lastMatch !== null) {
        matches.push(lastMatch[1]); // uid being mentioned
        lastMatch = re.exec(content);
    }

    // TODO: query user name from matched id

    // replace id with user name
    // fake usernames here
    var usernames = ['Random Name'];
    for (var i = 0; i < usernames.length; ++i) {
        content = content.replace(new RegExp(matches[i], 'g'), usernames[i]);
    }

    return content;
};

Vue.filter('username', filter);

But in my case, usernames should be achieved with AJAX of a query with id. How should I do it?

Anything you can do with a filter you can do with a computed. In Vue 2.0, there won't be filters, so you'll need to use computeds instead.

Fetching data asynchronously into a computed is a somewhat messy problem, which is why there is the vue-async-computed plugin . The difficulty is that the computed has to return a value synchronously, when it hasn't finished fetching data.

The solution is to have the computed depend on a cache of fetched data. If the needed value isn't in the cache, the computed kicks off the async process to fetch it and returns some placeholder value. When the process adds a value to the cache, the computed should notice the change in the cache and return the complete value.

In the demo below, I had to make an auxiliary variable, trigger , which I reference in the computed just so I know there's been an update. The fetch process increments trigger , which triggers the computed to re-evaluate. The computed doesn't notice when values are added to or updated in decodedIds . There may be a better way to deal with that. (Using async computed should make it a non-issue.)

 vm = new Vue({ el: 'body', data: { messages: [ 'Thank you @id-3124324!' ], decodedIds: {}, trigger: 0 }, computed: { decodedMessages: function() { return this.messages.map((m) => this.decode(m, this.trigger)); } }, methods: { decode: function(msg) { var re = /@(id\\-\\d+)/g; var matches = msg.match(re); for (const i in matches) { const p1 = matches[i].substr(1); if (!(p1 in this.decodedIds)) { // Indicate name is loading this.decodedIds[p1] = '(...)'; // Mock up fetching data setTimeout(() => { this.decodedIds[p1] = 'some name'; ++this.trigger; }, 500); } } return msg.replace(re, (m, p1) => this.decodedIds[p1]); } } }); setTimeout(() => { vm.messages.push('Added @id-12345 and @id-54321.'); }, 1500); 
 <script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script> <div v-for="message in decodedMessages"> {{message}} </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM