Question Set 1 Flashcards

1
Q

What you’ve done with Frontend technologies and what you have worked on.

A

Started with Angular back in 2016. I was responsible for maintaining various Angular applications that ran on the main Liveramp website.

I’ve built several small React apps, I probably have about a year of experience in React but it’s been around two years since I last used it.

I started programming in Vue in Williams Sonoma in 2021 building out product pages, assisting maintaining the current codebase, fetching and pushing data to external APIs. WS had various product pages, some simple (product image, price, buy button) while others were complex pages that included several options such as size, color, material, shipping options. The pages needed to dynamically update (price, delivery dates) as the user selected different options. A single page could be comprised of several components. State was managed by Vuex. We did not use a router. Navigation was primarily via http calls.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What were your deliverables on your projects

A

Widgets, updated HTML, new functionality, changes requested by marketing,

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Questions about micro frontends

A

Micro Frontends (MFE) is an architectural style for developing web applications as a collection of loosely coupled, independently deployable frontend microservices. The idea behind Micro Frontends is to apply the principles of microservices architecture to the frontend part of a web application.

Key concepts and characteristics of Micro Frontends include:

  1. Independence: Each micro frontend represents a self-contained piece of the user interface that can be developed, tested, and deployed independently. Teams can work on different parts of the application without tightly coupling their code.
  2. Autonomy: Teams responsible for different micro frontends have autonomy in their technology stack, development processes, and release cycles. This allows them to choose the tools and frameworks that best suit their specific requirements.
  3. Seamless Integration: Micro Frontends should seamlessly integrate into the overall user interface. They can be composed to form a cohesive and unified user experience. This integration can be achieved using various techniques, such as iframes, web components, or client-side routing.
  4. Isolation: Micro Frontends aim to isolate concerns and dependencies within each module. This helps in reducing the impact of changes in one part of the application on others and enhances maintainability.
  5. Dynamic Composition: Micro Frontends support dynamic composition, meaning that different versions of micro frontends can coexist in the same application. This is beneficial for incremental upgrades and A/B testing.
  6. Scalability: Micro Frontends can scale horizontally, allowing teams to scale independently based on their workload without affecting the entire application.
  7. Flexibility: The architecture allows for the use of different technologies, frameworks, and languages across micro frontends. Teams can choose the best tools for their specific requirements.

It’s important to note that while Micro Frontends offer advantages in terms of flexibility and scalability, they also introduce challenges related to communication between micro frontends, maintaining a consistent look and feel, and orchestrating the overall application. Successful implementation requires careful planning and consideration of these challenges.

Module Federation

Module Federation is a concept introduced by Webpack, a popular JavaScript module bundler. It’s a mechanism that allows you to dynamically load and share code between different JavaScript applications at runtime. This is particularly useful in a microservices or micro frontends architecture.

Here are key points about Module Federation:

1.	Dynamic Loading: With Module Federation, you can dynamically load JavaScript modules from different applications or micro frontends at runtime. This is different from traditional static bundling where everything is resolved at build time.
2.	Independently Deployable Micro Frontends: Module Federation enables the development of independently deployable micro frontends that can be composed together to form a larger application. Each micro frontend can be developed and deployed separately.
3.	Sharing Code: It allows sharing code between different parts of your application or even across multiple applications. This can include sharing components, utilities, or other JavaScript modules.
4.	Remote Containers: In a typical Module Federation setup, one application is considered the “host” or “container,” and it can dynamically load modules from other “remote” applications. This enables building scalable, modular applications.
5.	Webpack Configuration: Module Federation is configured in the Webpack configuration files of the involved applications. Webpack will handle the bundling and loading of modules at runtime.

Here’s a simple example of a Webpack configuration using Module Federation:

// webpack.config.js of the host application
const ModuleFederationPlugin = require(‘webpack/lib/container/ModuleFederationPlugin’);

module.exports = {
// other configurations…
plugins: [
new ModuleFederationPlugin({
name: ‘hostApp’,
remotes: {
remoteApp: ‘remoteApp@http://path-to-remote-app.com/remoteEntry.js’,
},
}),
],
};

In this example, the hostApp is configured to load modules from the remoteApp at runtime.

Module Federation simplifies the development of complex, distributed applications by allowing you to compose them dynamically. It’s especially valuable in scenarios where you have multiple teams working on different parts of a larger application or in a microservices architecture where services need to share code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

How to implement accessibility scenarios

A

Implementing accessibility scenarios in web development involves addressing various aspects to ensure that your websites or web applications are usable by people of all abilities and disabilities. Here are steps you can take:

  1. Semantic HTML:
    • Use semantic HTML elements to provide a clear and meaningful structure. For example, use <header>, <nav>, <main>, and <footer> appropriately.
  2. Keyboard Navigation:
    • Ensure that all interactive elements on your site can be navigated using the keyboard. This includes links, buttons, and form fields.
    • Implement visible focus styles to indicate the currently focused element.
  3. Screen Reader Compatibility:
    • Use meaningful text for links and buttons. Avoid generic phrases like “click here” and provide context.
    • Add descriptive alternative text for images using the alt attribute.
    • Test your website with screen readers to ensure a good user experience.
  4. Contrast and Color:
    • Maintain sufficient color contrast between text and background to make content readable for users with low vision or color blindness.
    • Avoid relying solely on color to convey information. Use additional visual cues or text labels.
  5. Resizable Text:
    • Ensure that users can zoom in or out without loss of content or functionality. Avoid setting font sizes in absolute units like pixels.
  6. Forms and Error Handling:
    • Use appropriate HTML elements for form inputs and labels. Associate labels with form fields.
    • Provide clear instructions and error messages. Ensure that users can understand and correct form errors.
  7. Focus Management:
    • Manage focus properly, ensuring that users can navigate through your site using only the keyboard.
    • Avoid trapping users in keyboard focus traps.
  8. Skip Navigation Links:
    • Include a “skip to content” link at the beginning of the page to allow users to skip repetitive navigation and go directly to the main content.
  9. Aria Roles and Attributes:
    • Use ARIA roles and attributes to enhance the accessibility of complex UI components, such as sliders, modals, and live regions.
    • Be cautious not to overuse ARIA; use it to complement native HTML semantics.
  10. Testing:
    • Regularly test your website with automated accessibility testing tools (e.g., Lighthouse, Axe).
    • Conduct manual testing with assistive technologies to ensure a comprehensive evaluation.
  11. User Testing:
    • Consider involving users with disabilities in your testing process to gather valuable feedback and insights.

By incorporating these practices, you can create a more inclusive and accessible web experience for all users. Keep in mind that accessibility is an ongoing process, and continuous testing and improvements are essential.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Questions on pagination

A

Implementing pagination in Vue.js typically involves managing the state of the current page and displaying a subset of data accordingly. Here’s a simple example of how you can achieve pagination in a Vue.js component:

  1. HTML Template:
    ```html
    <template>
    <div>
    <!-- Display the current page data -->
    <ul>
    <li v-for="item in paginatedData" :key="item.id">{{ item.name }}</li>
    </ul>

    <!-- Display pagination controls -->
    <div>
    <button @click="prevPage" :disabled="currentPage === 1">Previous</button>
    <span>{{ currentPage }} / {{ totalPages }}</span>
    <button @click="nextPage" :disabled="currentPage === totalPages">Next</button>
    </div>
    </div>
    </template>```
  2. Script Section:
    javascript
    <script>
    export default {
      data() {
        return {
          allData: [], // your complete data
          itemsPerPage: 5, // adjust as needed
          currentPage: 1,
        };
      },
      computed: {
        // Calculate the total number of pages
        totalPages() {
          return Math.ceil(this.allData.length / this.itemsPerPage);
        },
        // Calculate the subset of data for the current page
        paginatedData() {
          const start = (this.currentPage - 1) * this.itemsPerPage;
          const end = start + this.itemsPerPage;
          return this.allData.slice(start, end);
        },
      },
      methods: {
        // Move to the previous page
        prevPage() {
          if (this.currentPage > 1) {
            this.currentPage--;
          }
        },
        // Move to the next page
        nextPage() {
          if (this.currentPage < this.totalPages) {
            this.currentPage++;
          }
        },
      },
    };
    </script>

This example assumes you have a list of data (allData) that you want to paginate. Adjust the itemsPerPage variable according to your design, and the pagination controls will allow users to navigate through the pages. Pagination logic, like calculating the total pages and the subset of data for the current page, is handled in computed properties. The prevPage and nextPage methods update the currentPage accordingly.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you register a Vue component inside another component?

A

In Vue.js, you can register a component inside another component in two primary ways: globally and locally. Here’s how you can do each:

  1. Global Registration:
    • Global registration involves defining a Vue component globally, making it available for use in any part of your application.
    ```javascript
    // GlobalComponent.vue<template>
    <div>This is a global component</div>
    </template>
    <script>
    export default {
      // Component definition
    };
    </script>
    ``````javascript
    // main.js or another entry file
    import Vue from ‘vue’;
    import GlobalComponent from ‘./GlobalComponent.vue’;// Register the component globally
    Vue.component(‘global-component’, GlobalComponent);// Now ‘global-component’ can be used in any component template
    ``````javascript
    // AnotherComponent.vue<template>
    <div>
    <global-component></global-component>
    </div>
    </template>```
  2. Local Registration:
    • Local registration involves registering a component within the scope of another component. This makes the component available only to the component where it’s registered.
    ```javascript
    // LocalComponent.vue<template>
    <div>This is a local component</div>
    </template>
    <script>
    export default {
      // Component definition
    };
    </script>
    ``````javascript
    // ParentComponent.vue<template>
    <div>
    <local-component></local-component>
    </div>
    </template>
    <script>
    import LocalComponent from './LocalComponent.vue';
    
    export default {
      components: {
        'local-component': LocalComponent, // Local registration
      },
      // Component definition
    };
    </script>
    ```

In the local registration example, the LocalComponent is registered within the ParentComponent using the components option. This way, it’s only available within the scope of ParentComponent.

Choose the method that fits your application structure and the scope of your components. Global registration is suitable for components you plan to reuse across multiple parts of your application, while local registration is beneficial when you want to encapsulate components within specific parent components.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

How can you use local storage with Vue.js?

A

Using local storage with Vue.js involves leveraging the browser’s localStorage API to store and retrieve data. Here’s a simple example of how you can use local storage in a Vue.js component:

  1. Set Data in Local Storage:
    ```javascript
    // ExampleComponent.vue
    <template>
    <div>
    <input></input>
    <button @click="saveData">Save to Local Storage</button>
    </div>
    </template>
    <script>
    export default {
      data() {
        return {
          userData: '',
        };
      },
      methods: {
        saveData() {
          // Save data to local storage
          localStorage.setItem('user_data', JSON.stringify(this.userData));
        },
      },
    };
    </script>
    ```
  2. Retrieve Data from Local Storage:
    ```javascript
    // AnotherComponent.vue
    <template>
    <div>
    <p>Data from local storage: {{ retrievedData }}</p>
    </div>
    </template>
    <script>
    export default {
      data() {
        return {
          retrievedData: '',
        };
      },
      mounted() {
        // Retrieve data from local storage
        const storedData = localStorage.getItem('user_data');
        this.retrievedData = storedData ? JSON.parse(storedData) : '';
      },
    };
    </script>
    ```

In the first example (ExampleComponent.vue), the user’s data is saved to local storage when they click the “Save to Local Storage” button. The data is stored as a string, so we use JSON.stringify() to convert the data into a JSON string before saving.

In the second example (AnotherComponent.vue), the component retrieves the stored data from local storage during the mounted lifecycle hook. The retrieved data is then displayed in the template.

Remember that localStorage has limitations, such as a storage capacity of around 5 MB per domain and being synchronous, which could impact performance when dealing with large amounts of data. Additionally, be cautious about storing sensitive information in local storage due to potential security risks.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How do you create an instance of Vue.js?

A

Creating an instance of Vue.js involves using the Vue constructor function. Here’s a basic example of how you can create a Vue instance:

  1. Include Vue:
    • Make sure you include Vue.js in your project. You can do this by including it from a CDN, installing it via npm/yarn, or using a script tag.
    html
    <!-- Include Vue from CDN -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  2. Create Vue Instance:
    • Once Vue is included, you can create a Vue instance using the new Vue() constructor. Pass an object with various options to configure your Vue instance.
    ```html<div>
    {{ message }}
    </div>
    <script>
    // Create a new Vue instance
      const app = new Vue({
        el: '#app', // Mount the Vue instance to the element with id 'app'
        data: {
          message: 'Hello, Vue!',
        },
      });
    </script>
    ```In this example:
    - The el option specifies the HTML element to which the Vue instance is attached (in this case, an element with the id ‘app’).
    - The data option contains the reactive data for the instance. Any changes to the data will automatically update the associated views.
  3. Access Vue Instance:
    • You can access the Vue instance through the app variable and interact with its properties or methods.
    html
    <script>
      // Access the Vue instance and modify data
      app.message = 'Vue instance updated!';
    </script>

This is a basic example, and Vue instances can be configured with various options, such as methods, computed properties, lifecycle hooks, and more. The options you provide when creating a Vue instance depend on your specific application requirements.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How can you create two way bindings in Vue.js?

A

In Vue.js, you can achieve two-way data binding using the v-model directive. This directive provides a convenient way to create a binding between an input element and a data property, allowing changes in the input to automatically update the associated data property, and vice versa.

Here’s an example of how you can create two-way binding with v-model:

```html

<template>
<div>
<!-- Using v-model for two-way binding -->
<input></input>

<!-- Displaying the data property -->
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
  data() {
    return {
      message: '',
    };
  },
};
</script>

~~~

In this example:
1. The v-model directive is applied to the input element, binding it to the message data property.
2. When the user types into the input field, the message data property is automatically updated.
3. The content of the p element is bound to the same message data property, so it reflects any changes made through the input field.

This two-way binding simplifies the synchronization of data between the user interface and the underlying Vue instance. It’s commonly used with form inputs, making it easy to manage and respond to user input.

Keep in mind that v-model is a shorthand for handling input and output bindings. It’s especially useful for form elements like text inputs, checkboxes, and radio buttons. If you’re working with custom components, you might need to implement custom event handling to achieve a similar effect.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Explain the difference between slots and scoped slots.

A

In Vue.js, both slots and scoped slots are features that allow you to compose components and pass content or data between parent and child components. However, they serve different purposes and have distinct use cases.

  1. Slots:
    • Purpose: Slots provide a way to pass content from a parent component to a child component.
    • Usage: In the child component, you define a slot using the <slot> element. In the parent component, any content placed between the opening and closing tags of the child component will be inserted into the corresponding slot.
    • Example:```html
      <!-- ChildComponent.vue --><template>
      <div>
      <h2>This is the child component</h2>
      <slot></slot>
      </div>
      </template>``````html
      <!-- ParentComponent.vue --><template>
      <child-component>
      <p>This content goes into the slot.</p>
      </child-component>
      </template>```
  2. Scoped Slots:
    • Purpose: Scoped slots extend the functionality of slots by allowing the child component to pass data back to the parent component.
    • Usage: In the child component, you define a scoped slot using the <slot> element with a name attribute. You can then bind data to this slot using the v-slot directive in the parent component.
    • Example:```html
      <!-- ChildComponentWithScope.vue --><template>
      <div>
      <h2>This is the child component with a scoped slot</h2>
      <slot :data="internalData"></slot>
      </div>
      </template>
      <script>
      export default {
        data() {
          return {
            internalData: 'Data from child',
          };
        },
      };
      </script>
      ``````html
      <!-- ParentComponentWithScope.vue --><template>
      <child-component-with-scope>
      <p>{{ data }}</p>
      </child-component-with-scope>
      </template>```

In summary, regular slots are primarily for passing content from parent to child, while scoped slots provide a mechanism for passing data from child to parent in addition to content. Scoped slots are especially useful when you want to create more dynamic and flexible component compositions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Explain Vue.js reactivity and common issues when tracking changes.

A

Vue.js reactivity is a fundamental concept that enables automatic and efficient updating of the user interface based on changes to the underlying data. It’s achieved through a reactive system that tracks dependencies between data properties and the components that use them. When the data changes, Vue automatically updates the affected parts of the DOM.

Here’s how Vue.js reactivity works:

  1. Data Properties:
    • Declare data properties in the data option of a component.
    javascript
    export default {
      data() {
        return {
          message: 'Hello, Vue!',
        };
      },
    };
  2. Template Binding:
    • Bind data properties to the template using expressions.
    ```html<template>
    <div>
    <p>{{ message }}</p>
    </div>
    </template>```
  3. Reactivity:
    • Vue automatically establishes a reactive dependency between the template and the data properties. When the data changes, Vue efficiently updates the template.

Common issues when tracking changes:

  1. Direct Property Addition:
    • Adding new properties directly to an object doesn’t trigger reactivity. Use Vue.set or this.$set to add reactive properties.
    ```javascript
    // Incorrect
    this.myObject.newProperty = ‘new value’;// Correct
    Vue.set(this.myObject, ‘newProperty’, ‘new value’);
    ```
  2. Array Changes:
    • Changing an array’s length directly doesn’t trigger reactivity. Use array methods like push, pop, shift, and splice to ensure reactivity.
    ```javascript
    // Incorrect
    this.myArray.length = 0;// Correct
    this.myArray.splice(0, this.myArray.length);
    ```
  3. Async Updates:
    • Asynchronous operations like setTimeout might lead to issues if data changes are not properly tracked. Use Vue’s nextTick or utilize proper async patterns.
    ```javascript
    // Incorrect
    setTimeout(() => {
    this.message = ‘Updated after timeout’;
    console.log(this.$el.textContent); // Might not reflect the update
    }, 1000);// Correct
    setTimeout(() => {
    this.message = ‘Updated after timeout’;
    this.$nextTick(() => {
    console.log(this.$el.textContent); // Reflects the update
    });
    }, 1000);
    ```
  4. Mutation Outside Vue:
    • Changing data outside of Vue (e.g., in a non-reactive utility function) may lead to issues. Try to keep mutations within Vue components to ensure proper reactivity.
    ```javascript
    // Incorrect
    function updateDataExternally() {
    myVueInstance.dataProperty = ‘New value’;
    }// Correct
    methods: {
    updateDataWithinVue() {
    this.dataProperty = ‘New value’;
    },
    }
    ```

By understanding these aspects of Vue.js reactivity and following best practices, you can ensure a smooth and predictable update of your components based on changes in data.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What are mixins? Describe their benefits and drawbacks.

A

Mixins in Vue.js are a way to encapsulate and reuse component features by composing them from multiple sources. A mixin is essentially an object containing component options (data, methods, lifecycle hooks) that can be merged with the options of a component.

Benefits of Mixins:

  1. Code Reusability: Mixins allow you to reuse and share functionality across multiple components. This helps in avoiding code duplication and maintaining a modular codebase.
  2. Encapsulation: Mixins provide a way to encapsulate specific features or behaviors into standalone modules. This improves code organization and makes it easier to reason about each part of your application.
  3. Flexibility: Mixins can be applied to components selectively. This means you can choose which components receive specific features, providing flexibility in component composition.
  4. Dynamic Composition: Mixins are dynamic, meaning you can apply them at runtime. This dynamic nature allows for flexible and dynamic component composition.

Drawbacks of Mixins:

  1. Naming Conflicts: If different mixins define methods or properties with the same names, you might encounter naming conflicts. This can lead to unexpected behavior and make the code harder to understand.
  2. Implicit Dependencies: Mixins introduce implicit dependencies between components and mixins. Understanding the behavior of a component might require examining multiple sources (components and mixins), which can complicate code maintenance.
  3. Order of Application: The order in which mixins are applied can impact the behavior of the component. If not managed carefully, this can lead to unexpected results, making code harder to maintain.
  4. Complexity: As the number of mixins increases, the complexity of understanding how different pieces of code interact can grow. This might make the codebase harder to grasp for developers who are not familiar with all the mixins in use.
  5. Global Scope: Mixins are often registered globally, which means they can impact multiple components. This global scope can make it challenging to track and manage changes.

When using mixins, it’s important to carefully document their usage, avoid naming conflicts, and consider alternatives like scoped slots, higher-order components, or Composition API for more explicit and structured code. Understanding the specific benefits and drawbacks of mixins will help you make informed decisions about their use in your Vue.js projects.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is a single-file component?

A

In Vue.js, a single-file component (SFC) is a file that contains a Vue component in a single file, typically with the extension .vue. It encapsulates the template, script, and style of a component in a cohesive unit. This helps in organizing and maintaining the structure of Vue.js applications.

A typical single-file component looks like this:

```html

<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
};
</script>

<style>

/* Add component-specific styles here */
</style>

~~~

Here’s what each section in a single-file component does:

  • Template Section (<template>): Contains the HTML template of the component. This is where you define the structure of your component.
  • Script Section (<script>): Contains the JavaScript code for the component. This is where you define the component’s data, methods, lifecycle hooks, and other options.
  • Style Section (<style>): Contains the component-specific styles. These styles are scoped to the component, meaning they won’t affect other components with the same class or tag names.

Benefits of Single-File Components:

  1. Modularity: Encapsulating the template, script, and style in a single file enhances modularity. Each component is self-contained, making it easier to manage and reason about.
  2. Scoped Styles: The styles defined in the <style> section are scoped to the component, preventing unintended style collisions with other components.
  3. Readability: The separation of concerns into distinct sections (template, script, style) improves code readability. Developers can quickly understand the structure, behavior, and styling of a component.
  4. Build Integration: Single-file components can be seamlessly integrated into build systems using tools like Vue CLI or webpack. These tools can preprocess and bundle the components for optimized performance.

Vue CLI, which is the official Vue.js command-line interface, supports the development and building of projects using single-file components.

To use a single-file component in a Vue.js project, you typically import it in another component or directly reference it in the main application. The build tools take care of processing and bundling the components appropriately.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Describe data flow between components in a Vue.js app

A

In a Vue.js application, the data flow between components follows a unidirectional flow, which means that data typically flows from parent components to child components through props, and child components communicate with parents through events. Here’s a breakdown of the data flow:

  1. Parent to Child:
    • Props: Parent components pass data down to child components using props. Props are custom attributes that you can register on a component, allowing the parent to pass data to the child.
    ```html
    <!-- ParentComponent.vue --><template>
    <child-component :message="parentMessage"></child-component>
    </template>
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent,
      },
      data() {
        return {
          parentMessage: 'Hello from parent!',
        };
      },
    };
    </script>
    ``````html
    <!-- ChildComponent.vue --><template>
    <div>
    <p>{{ message }}</p>
    </div>
    </template>
    <script>
    export default {
      props: ['message'],
    };
    </script>
    ```
  2. Child to Parent:
    • Events: Child components emit events to communicate with their parent components. The parent can listen for these events using the v-on directive.
    ```html
    <!-- ChildComponent.vue --><template>
    <button @click="sendMessageToParent">Send Message to Parent</button>
    </template>
    <script>
    export default {
      methods: {
        sendMessageToParent() {
          this.$emit('childEvent', 'Message from child!');
        },
      },
    };
    </script>
    ``````html
    <!-- ParentComponent.vue --><template>
    <div>
    <child-component @childEvent="handleChildEvent"></child-component>
    <p>{{ receivedMessage }}</p>
    </div>
    </template>
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent,
      },
      data() {
        return {
          receivedMessage: '',
        };
      },
      methods: {
        handleChildEvent(message) {
          this.receivedMessage = message;
        },
      },
    };
    </script>
    ```
  3. Sibling Components:
    • When sibling components need to communicate, you can use a shared parent component to manage the state and pass data down to the siblings through props or emit events up to the shared parent.
    ```html
    <!-- ParentComponent.vue --><template>
    <div>
    <sibling-a :dataA="sharedData" @updateDataA="handleUpdateDataA"></sibling-a>
    <sibling-b :dataB="sharedData" @updateDataB="handleUpdateDataB"></sibling-b>
    </div>
    </template>
    <script>
    import SiblingA from './SiblingA.vue';
    import SiblingB from './SiblingB.vue';
    
    export default {
      components: {
        SiblingA,
        SiblingB,
      },
      data() {
        return {
          sharedData: 'Shared Data',
        };
      },
      methods: {
        handleUpdateDataA(newData) {
          this.sharedData = newData;
        },
        handleUpdateDataB(newData) {
          this.sharedData = newData;
        },
      },
    };
    </script>
    ``````html
    <!-- SiblingA.vue --><template>
    <div>
    <p>Data in Sibling A: {{ dataA }}</p>
    <button @click="updateDataA">Update Data A</button>
    </div>
    </template>
    <script>
    export default {
      props: ['dataA'],
      methods: {
        updateDataA() {
          this.$emit('updateDataA', 'Updated Data in Sibling A');
        },
      },
    };
    </script>
    ``````html
    <!-- SiblingB.vue --><template>
    <div>
    <p>Data in Sibling B: {{ dataB }}</p>
    <button @click="updateDataB">Update Data B</button>
    </div>
    </template>
    <script>
    export default {
      props: ['dataB'],
      methods: {
        updateDataB() {
          this.$emit('updateDataB', 'Updated Data in Sibling B');
        },
      },
    };
    </script>
    ```

This unidirectional data flow makes Vue.js applications more predictable and easier to understand, as it enforces a clear structure for data communication between components. Components are decoupled, making them reusable and maintainable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

List the most common cause of memory leaks in Vue.js apps and how they can be solved.

A

Memory leaks in Vue.js applications can occur due to various reasons. Here are some common causes and solutions:

  1. Event Listeners:
    • Cause: Not properly removing event listeners can lead to memory leaks. For instance, if you attach an event listener in a component and forget to remove it when the component is destroyed, the listener can persist in memory.
    • Solution: Use the beforeDestroy lifecycle hook to remove event listeners. This ensures that event listeners are cleaned up when the component is about to be destroyed.
    javascript
    beforeDestroy() {
      // Remove event listeners here
      window.removeEventListener('resize', this.handleResize);
    }
  2. Component References:
    • Cause: Keeping references to components or elements, even after they are destroyed, can lead to memory leaks.
    • Solution: Avoid unnecessary component or DOM element references. If references are necessary, ensure that they are cleared or set to null in the beforeDestroy hook.
    javascript
    beforeDestroy() {
      this.myComponent = null; // or this.myElement = null;
    }
  3. Watchers and Computed Properties:
    • Cause: Incorrect usage of watchers or computed properties can lead to unintentional retention of objects in memory.
    • Solution: Be mindful of how you use watchers and computed properties. Avoid creating unnecessary dependencies that may retain objects longer than needed.
  4. Async Operations:
    • Cause: Unhandled promises or other async operations can keep components alive, causing memory leaks.
    • Solution: Ensure that async operations are properly handled, and clean up resources in the beforeDestroy hook. Use tools like Promise.all to handle multiple promises.
    javascript
    beforeDestroy() {
      // Clean up async resources
      this.cancelAsyncTask();
    }
  5. Global Event Bus:
    • Cause: A global event bus (e.g., using Vue’s $on and $emit) can lead to memory leaks if event listeners are not removed when components are destroyed.
    • Solution: Explicitly remove event listeners using this.$off in the beforeDestroy hook.
    javascript
    beforeDestroy() {
      this.$off('custom-event');
    }
  6. Long-lived Objects:
    • Cause: Keeping objects alive for a longer duration than necessary can lead to memory leaks.
    • Solution: Be mindful of the lifespan of objects. Clear or set to null any references that are no longer needed.
    javascript
    beforeDestroy() {
      this.longLivedObject = null;
    }
  7. Heavy DOM Manipulation:
    • Cause: Frequent or heavy DOM manipulations can lead to memory leaks.
    • Solution: Use Vue’s reactivity system and virtual DOM efficiently. Avoid direct DOM manipulations whenever possible.

These solutions aim to address common scenarios that can cause memory leaks in Vue.js applications. Regularly inspecting your code for these patterns and following best practices will help mitigate the risk of memory leaks. Additionally, using browser developer tools, such as Chrome DevTools, can assist in identifying memory-related issues in your application.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What is the virtual DOM and how is it beneficial?

A

The Virtual DOM (Document Object Model) is a programming concept used by frameworks like Vue.js and React to improve the efficiency of updating the user interface. Instead of directly manipulating the real DOM, these frameworks create a virtual representation of the DOM in memory, known as the Virtual DOM. This virtual representation mirrors the structure and state of the actual DOM.

Here’s how the Virtual DOM works and its benefits:

  1. Virtual DOM Structure:
    • When you make changes to your application’s state (e.g., updating data), the framework doesn’t immediately update the real DOM. Instead, it creates a virtual representation of the DOM with the updated state.
  2. Diffing Algorithm:
    • The framework then performs a process called “diffing” to compare the virtual DOM with the previous version. It identifies the minimal number of changes needed to bring the virtual DOM in sync with the actual DOM.
  3. Patch Operations:
    • Once the differences are determined, the framework generates a set of patch operations required to update the real DOM. These operations are optimized and aim to minimize the impact on the actual DOM.
  4. Efficient Updates:
    • Finally, the patch operations are applied to the real DOM, updating only the specific elements that changed. This approach is more efficient than directly manipulating the entire DOM, especially for complex and dynamic user interfaces.

Benefits of the Virtual DOM:

  1. Performance Improvement:
    • Updating the real DOM can be a costly operation, especially when dealing with complex UIs or frequent updates. The Virtual DOM allows frameworks to optimize this process, reducing the number of actual DOM manipulations and improving performance.
  2. Batched Updates:
    • Changes to the virtual DOM can be batched together and applied in a single update, minimizing the number of times the real DOM needs to be manipulated. This batching improves the efficiency of rendering updates.
  3. Cross-Browser Consistency:
    • The Virtual DOM helps in handling inconsistencies across different browsers and devices. The framework can generate the appropriate patch operations to ensure a consistent view of the UI.
  4. Developer Convenience:
    • Working with a virtual representation of the DOM simplifies the development process. Developers can work with a reactive programming model, updating the application state, and letting the framework handle the details of efficiently updating the UI.

Both Vue.js and React utilize the Virtual DOM to achieve these benefits, contributing to a more responsive and performant web application.

17
Q

How to reset “deeply nested state property” in Vuex store.

A

To reset a deeply nested state property in a Vuex store, you should follow a reactive approach by creating a mutation that updates the nested property to its initial state. Here’s an example of how you can achieve this:

Assuming you have a state structure like this in your Vuex store:

```javascript
// vuex store
const store = new Vuex.Store({
state: {
deeplyNested: {
nestedObject: {
propertyToReset: ‘initialValue’,
// other nested properties…
},
// other properties…
},
// other state properties…
},
mutations: {
resetDeeplyNestedProperty(state) {
state.deeplyNested.nestedObject.propertyToReset = ‘initialValue’;
},
},
// other Vuex store configurations…
});
~~~

In this example, the mutation resetDeeplyNestedProperty is created to reset the propertyToReset to its initial value. You can commit this mutation from your components using the commit method or mapMutations helper.

For instance, in a component:

```javascript
// component script
export default {
methods: {
resetProperty() {
this.$store.commit(‘resetDeeplyNestedProperty’);
},
},
};
~~~

Now, calling resetProperty in your component will trigger the mutation, resetting the deeply nested property to its initial value.

Remember to adjust the mutation according to your actual state structure. If your state structure is more complex, you might need to navigate deeper into the nested objects or arrays to reach the property you want to reset.

18
Q

How to mock API calls in unit tests

A

JavaScript Libraries for API Mocking
There are multiple JavaScript libraries available for API mocking. Selecting a suitable library is the first step. Here are some of the most used JavaScript API mocking libraries:

JSON Server⁠—A fast and efficient node module that allows creating a REST JSON web service quickly.
MirageJS⁠—This is an API mocking library for building, testing, and sharing JavaScript applications independent of back-end services.
Nock⁠—An HTTP server mocking library ideal for testing front-end components by making HTTP requests.
Axios-mock-adapter⁠—A JavaScript library for sending HTTP requests to APIs.
Faker—This is a famous library for generating fake data for testing.

19
Q

How to use Vue’s shallowMount() to test only specific components in Vue

A

In Vue.js testing with Jest and other testing libraries, shallowMount is a function provided by the testing utilities to create a shallow wrapper for a Vue component. This wrapper represents the component with its child components stubbed, meaning that the child components are not rendered or fully mounted.

Here’s a basic explanation of shallowMount:

  1. Shallow Rendering:
    • shallowMount allows you to perform shallow rendering, meaning that only the tested component is rendered, and its direct child components are stubbed. Child components are replaced with placeholder elements, and their lifecycle hooks are not called.
  2. Benefits:
    • Shallow rendering is useful when you want to isolate the testing scope to the component under test and avoid the full rendering of child components. This can improve test performance and make tests more focused on the component’s logic.
  3. Example:
    • Here’s an example of using shallowMount in a Jest test:```javascript
      import { shallowMount } from ‘@vue/test-utils’;
      import MyComponent from ‘@/components/MyComponent.vue’;describe(‘MyComponent’, () => {
      it(‘renders correctly’, () => {
      // Shallow mount the component
      const wrapper = shallowMount(MyComponent);
      // Your test assertions go here
      expect(wrapper.text()).toContain('Hello, Vue!');   }); }); ```
    In this example, shallowMount is used to create a shallow wrapper for MyComponent, and then assertions can be made based on the rendered output of the component.
  4. When to Use:
    • Use shallowMount when you want to test the behavior and rendering of a component in isolation, without deeply rendering its child components. It’s particularly useful for unit testing individual components.

Keep in mind that the appropriate choice between shallowMount and mount (which fully renders the component and its children) depends on your testing goals and the level of isolation you want in your tests.

20
Q

Explain Git rebase, interactive rebase

A

Git rebase is a powerful Git command used to reapply a sequence of commits onto a different base commit. It allows you to rewrite commit history by moving, combining, or removing commits. The primary use case for rebase is to create a cleaner, more linear commit history.

Interactive rebase is a specific form of rebase that allows you to interactively edit commit history. You can use it to reorder commits, squash multiple commits into one, edit commit messages, and more.

Here’s an overview of Git rebase and interactive rebase:

  1. Basic Syntax:
    bash
    git rebase <base>
  2. Common Use Cases:
    • Merge Branches:
      bash
      git checkout feature-branch
      git rebase main
    • Squash Commits:
      bash
      git rebase -i HEAD~3  # Rebase last 3 commits
    • Edit Commit Messages:
      bash
      git rebase -i HEAD~3  # Mark commits for editing
  3. Workflow:
    • Switch to the branch you want to rebase.
    • Specify the base commit you want to rebase onto.
    • Git will temporarily save your changes, apply the commits from the base commit, and then reapply your changes on top.
  1. Basic Syntax:
    bash
    git rebase -i <base>
  2. Common Use Cases:
    • Reorder Commits:
      bash
      git rebase -i HEAD~3  # Open interactive rebase for last 3 commits
    • Squash Commits:
      bash
      git rebase -i HEAD~3  # Mark commits for squashing
    • Edit Commit Messages:
      bash
      git rebase -i HEAD~3  # Mark commits for editing
  3. Interactive Rebase File:
    • Git opens an interactive rebase file in your default text editor.
    • Each line represents a commit with an action.
    • Actions include “pick,” “reword,” “edit,” “squash,” “fixup,” and more.
  4. Editing Commits:
    • Change “pick” to “edit” to stop at that commit.
    • Git will pause at each commit marked for editing.
    • Perform necessary changes, then use git commit --amend or git rebase --continue.
  5. Squashing Commits:
    • Change “pick” to “squash” or “s” for the commits you want to squash.
    • Git will prompt you to edit the commit message.
  6. Reordering Commits:
    • Change the order of lines in the interactive rebase file.
  7. Finishing the Rebase:
    • After editing, save and close the interactive rebase file.
    • Complete the rebase with git rebase --continue or git rebase --abort if needed.

Interactive rebase gives you fine-grained control over your commit history, but use it with caution, especially if you’re rebasing commits that have already been pushed to a shared repository, as it rewrites commit history.

21
Q

Explain code review best practices

A

Code reviews play a crucial role in maintaining code quality, fostering collaboration, and catching issues early in the development process. Here are some best practices for effective code reviews:

  1. Set Clear Objectives:
    • Clearly communicate the goals and expectations of the code review. Define what aspects should be reviewed (e.g., logic, code structure, style, performance).
  2. Timing:
    • Conduct code reviews regularly and promptly to avoid unnecessary delays in the development process.
  3. Keep Changes Small:
    • Break down large changes into smaller, more manageable units. This makes reviews more focused and easier to understand.
  1. Automated Tools:
    • Use automated tools for static code analysis, linting, and formatting. These tools help catch common issues early and maintain consistent coding standards.
  2. Be Constructive:
    • Provide feedback in a constructive and positive manner. Focus on the code, not the person. Use “I” statements and suggest improvements rather than making demands.
  3. Ask Questions:
    • If something is unclear, ask questions for clarification. This helps to avoid making assumptions and ensures a better understanding of the code.
  4. Review the Whole Context:
    • Understand the broader context of the changes. Consider how the changes fit into the overall architecture and whether they align with the project’s goals.
  5. Check for Edge Cases:
    • Pay attention to edge cases and consider different scenarios. Ensure that the code handles various inputs, error conditions, and unexpected situations.
  6. Use a Checklist:
    • Create or follow a checklist of common issues or best practices during code reviews. This ensures a systematic approach and helps reviewers cover all necessary aspects.
  7. Verify Requirements:
    • Ensure that the code meets the specified requirements and aligns with the user stories or tasks associated with it.
  1. Summarize and Document Feedback:
    • Summarize the feedback provided during the code review. Document agreed-upon changes, decisions, and action items.
  2. Encourage Iteration:
    • Encourage the author to iterate on the code based on the feedback received. Follow up to verify that suggested changes have been implemented.
  3. Avoid “Ship It” Mentality:
    • Avoid rushing through the review process. Ensure that the code
22
Q

Explain reusable components

A

In Vue.js, reusable components are a fundamental concept that allows you to create modular, self-contained units of code that can be easily reused throughout your application. Components in Vue.js encapsulate a piece of UI, along with its behavior and styling, making it a powerful and scalable way to build complex user interfaces. Here’s an explanation of reusable components in Vue.js:

  • In Vue.js, you can define a component using the Vue.component method or by creating a single-file component with a .vue extension.
javascript
   // Example using Vue.component method
   Vue.component('my-component', {
     // Component options (template, data, methods, etc.)
   });
  
  • Single-file components are a common and recommended way to define reusable components in Vue.js. They encapsulate the template, script, and style of a component in a single file.

```html
<!-- MyComponent.vue -->

<template>
<div>
<h1>{{ title }}</h1>
<!-- Component template -->
</div>
</template>

<script>
export default {
     data() {
       return {
         title: 'Hello, Vue!',
       };
     },
     // Component methods, lifecycle hooks, etc.
   };
</script>

<style>

   /* Component-specific styles */
   
</style>

```

  • Once defined, a component can be reused in different parts of your application. You can include a component in another component’s template or in the main application template.

```html
<!-- App.vue -->

<template>
<div>
<my-component></my-component>
<my-component></my-component>
</div>
</template>

<script>
import MyComponent from './MyComponent.vue';

   export default {
     components: {
       'my-component': MyComponent,
     },
   };
</script>

```

  • Components can accept data from their parent components using props. Props are custom attributes you can define on a component, allowing you to pass data into it.

```html
<!-- ParentComponent.vue -->

<template>
<div>
<child-component :message="parentMessage"></child-component>
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

   export default {
     components: {
       'child-component': ChildComponent,
     },
     data() {
       return {
         parentMessage: 'Hello from parent!',
       };
     },
   };
</script>

```

```html
<!-- ChildComponent.vue -->

<template>
<div>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
     props: ['message'],
   };
</script>

```

  • Components can communicate with their parent components using custom events. Child components can emit events, and parent components can listen for those events.

```html
<!-- ChildComponent.vue -->

<template>
<button @click="sendMessageToParent">Send Message to Parent</button>
</template>

<script>
export default {
     methods: {
       sendMessageToParent() {
         this.$emit('childEvent', '
</script>
23
Q

How to debug the application locally

A

To debug a JavaScript application locally, you can use browser developer tools or other debugging tools. In browsers like Chrome or Firefox, press F12 or right-click and select “Inspect” to open developer tools. Navigate to the “Sources” or “Debugger” tab, set breakpoints, and inspect variables during runtime. Alternatively, use console.log() statements for logging relevant information. For Node.js, you can use the built-in debugger or tools like node-inspect.

24
Q

Accessibility: How to focus over list items using keyboard

A

To make list items focusable using the keyboard, you should ensure that they have the appropriate HTML attributes and styles. Here’s a simple example using HTML and CSS:

```html
<!DOCTYPE html>

<html>
<head>
<meta></meta>
<meta></meta>
<title>Accessible List</title>

</head>
<body>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</body>
</html>

~~~

Key points:

  1. Add tabindex="0" to each list item to make them focusable.
  2. Use CSS to provide a visual indication when an item is focused. The example uses an outline, but you can customize this based on your design.

Now, users can navigate through the list items using the keyboard, and the focused item will have a visible outline. This ensures a better user experience for those relying on keyboard navigation or screen readers.