What is the process for binding attributes using v-bind with a one-time binding?

Currently, I am utilizing the vue-i18n library for localization purposes. An issue I have encountered is when attempting to translate input placeholders using the following syntax:

<input type="text" v-model="someValue" :placeholder="$t('translation.string')">

The problem lies in the fact that each time the component re-renders, the $t() function gets executed unnecessarily (as mentioned in the library documentation). This results in a large number of redundant function calls in my basic booking form, which is something I want to avoid.

Is there a way to bind the attribute only once? It's crucial to note that the translated value remains constant throughout the Vue instance's lifecycle. Using v-once is not suitable in this scenario since I aim to retain reactivity within the component/node while 'hardcoding' the attribute.

While I acknowledge that storing the translated strings in the data object could resolve the issue, I am wondering if there exists a simpler, alternative solution that doesn't involve extensive code duplication.

Answer №1

If you're seeking a solution where only a single run is guaranteed, using a computed property is the way to go. Computed properties in Vue will trigger a re-run only when their dependencies change. Hence, with this.$t('LOCALE.STRING') remaining constant unless the locale changes, Vue will cache the value for subsequent renders.

<template>
  ...
  <input
    ...
    :placeholder="translatedPlaceholder"
  >
  ...
</template>

<script>
  ...
  computed: {
    translatedPlaceholder() {
      return $t('translation.string');
    },
  },
  ...
</script>

An added benefit of this approach is that if the locale does change, Vue will refresh the computed property accordingly, ensuring the correct value is displayed.


I have created an interactive snippet to illustrate this syntax further, providing a more detailed example.

The snippet contains a basic localized greeting followed by a random number within a <p> tag, along with two buttons. The localized string in the text is accessed through a computed property.

The first button generates a new number, triggering a re-render of the <p> element in the DOM.
The second button switches the locale, prompting Vue-i18n to update the localized string.

Every execution of the computed localization property logs to the console.
I've also set up logging to the console whenever Vue updates the DOM.

const messages = {
  en: {
    "greeting": 'Hello!',
  },
  es: {
    "greeting": '¡Hola!',
  },
};

new Vue({ 
  i18n: new VueI18n({
    locale: 'en',
    messages,
  }),
  data() {
    return {
      num: 1,
    }
  },
  computed: {
    localizedGreeting() {
      console.log('Computed executed');
      return this.$t('greeting');
    },
  },
  methods: {
    swapLocale() {
      this.$i18n.locale = (this.$i18n.locale == 'en' ? 'es' : 'en');
    },
    randomNum() {
      this.num = Math.floor(Math.random() * 10000);
    },
  },
  updated() {
    console.log('DOM updated');
  },
}).$mount('#app')
.as-console-wrapper {
  max-height: 120px !important;
}
<script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-i18n@8"></script>

<div id="app">
  <p>{{ `${localizedGreeting} #${num}` }}</p>
  <button @click="randomNum()">Re-render Greeting</button>
  <button @click="swapLocale">Swap Greeting Locale</button>
</div>

As demonstrated, re-rendering does not cause the computed property to re-execute, while changing the locale triggers it, aligning perfectly with our requirements.


Finally, it's worth noting that though there may be a slight performance impact in your initial code due to the recurring $t() calls, the actual difference is likely minimal. Prioritize simplicity over optimizing for performance unless absolutely necessary.

Always remember, premature optimization is the root of all evil!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is causing my autocomplete input to malfunction?

Greetings, I am new here and this is my first question. Currently, I am working on creating an autocomplete search bar for a weather app using an input field that filters a JSON file to display matching places starting with the same letter. However, I have ...

Are you making alterations to the URL?

Is there a way to change the displayed URL on a webpage to show "bananas" instead of "http://example.com/" after the page has loaded? ...

Utilizing ng-model-options updateOn:blur in conjunction with the uib-datepicker popup

There is an input field where a user can either enter a date manually or choose one from the uib-datepicker calendar (https://angular-ui.github.io/bootstrap/). When the user clicks on the input, the calendar pops up for date selection. Here is the input co ...

Highcharts facing issues with data rendering

This is the JSON data I have: [ { "project_title":"sdsdsd", "project_ref_id":"112", "amount":"232323.00", "months":"Mar-2015" },{ "project_title":"test project 44", "project_ref_id":"113", "a ...

Loading a page with a subtle fade-in effect using jQuery

Looking to add some jQuery functionality to my navigation menu in order to have the page wrapper fade in and out when a main nav link is clicked. While the code itself is functioning properly, I am encountering a couple of issues: There is a brief flash ...

Sharing data between ejs and javascript files

When using Express, I have encountered an issue with passing a variable to an EJS file called "index.ejs". res.render("index",{passedUser:req.user.alias}) Although I am able to successfully print it using <%=passedUser%> in the EJS file, I require ...

Flexbox Resizing Notification(?)

Recently, I've been utilizing flexbox in my layout design and it has been a game-changer. However, I am facing an issue that might be linked to my heavy use of AngularJS, particularly the ng-include feature. The specific problem arises when I incorpo ...

Convert JavaScript back into an HTML attribute

Is there a way to include a JavaScript code in an HTML attribute like shown below? <div class="xx" animation="yy" animate-duration="<script>Code goes here<script>" ...> </div> I'm struggling to figure it out, is there a solut ...

Is there a way to automatically dismiss a notify.js notification?

I am currently attempting to forcefully close an opened notification by clicking a button, following the instructions provided in the advanced example of the notify.js API. Can someone please explain how this can be accomplished? function CLOSE() { $( ...

Function asynchronously returning Promise even after Await statement is executed

I've been attempting to develop a function that retrieves data from a document in the Firebase database using Nodejs: module.exports = async (collectionName, documentId, res) => { const collection = db.doc(`/${collectionName}/${documentId}`); t ...

Steps for launching a hyperlink in a browser on Vue Native

I'm having trouble finding information on how to properly use the Linking component in react-native. The resources available are limited, and I'm not sure if I am implementing it correctly... Below is what I have in my template: <nb-button :o ...

angular: handling duplicates in ng-repeat

Here is the JSON data: streams = [{ id: 0, codec_type: 'video', content: '1920x1040 - H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10' }, { id: 1, codec_type: 'audio', content: '5.1(side) - cze - undefined' }, ...

Is it possible to access specific elements of an array in Node.js by their index in the storage?

Just wanted to give a heads up - I’m still getting the hang of things, so there’s a chance my approach may not be quite right! I’ve got a Javascript application (in Node.js) that needs to fill up a database - specifically, it’s an array with 88 mi ...

The TypeScript rule in the project-specific .eslintrc.js file is not being applied as expected

Currently, I am following a tutorial on Ionic/Vue 3 which can be found here. However, when I try to serve the project, I encounter the following error: https://i.stack.imgur.com/k4juO.png It appears that my project-level .eslintrc.js file is not being ap ...

Choosing a picture element based on the source attribute for identification

Currently, I am in the process of writing a script for a webpage and I find myself needing to update the icon associated with an image. The issue lies in the fact that the image only contains a tag structured like this: <img src="/pic1.png" alt="clear" ...

Tips for passing props in Vue 3 and Vue Router 4 when utilizing router-view exclusively for a particular component

My routing and props are functioning properly, but I am facing an issue where the msg prop is being sent to every component loaded by the router. Is there a workaround for this situation? In App.vue, which serves as my base component, I have: <templat ...

Tips for properly handling special characters in AJAX-loaded content?

During my ajax call, I encountered the following issue upon success: success: function(html){ var product_json = []; data=$(html); $(".product_json", data).each(function(){ product_json.push( jQuery.parseJSON( $(this).html() ) ); }); .... //code co ...

When working with DNN, I attempted to redirect using JavaScript code, but found that I continue to see the same page after the form submission code

Here is the code I am using to submit a form. When the button is clicked, it will trigger the Checkout() function. function postURL(url) { var form = $('<form action="' + url + '" method="post">' + "<input type=& ...

Include "clickable" commas among various <span> elements

Struggling to insert commas between a series of items? Well, fear not! If you're wondering how, it can be achieved with a simple line of code: .comma:not(:last-of-type)::after{ content: ", "; } <span class="comma">A</span> <s ...

Is the length of a complex match in Angular JS ng-if and ng-repeat greater than a specified value?

In my code, there is an ng-repeat that generates a table based on one loop, and within each row, another cell is populated based on a different loop: <tbody> <tr ng-repeat="r in roles | limitTo: 30"> <td>{{r.name}}</td> ...