adnenre
#Vux#frontend

nutui component library

NutUI deep dive into the mobile UI component library

NutUI is a mobile UI component library developed by JD.com. It provides a rich set of components for building high‑quality mobile web apps with Vue 3. It supports both Vue 2 and Vue 3, with extensive documentation and a design system tailored for e‑commerce and enterprise applications.


#Installation

#Using npm

npm install @nutui/nutui

#Using yarn

yarn add @nutui/nutui

#Basic Usage

#Full Import

Import all components globally in your main.js:

import { createApp } from 'vue';
import App from './App.vue';
import NutUI from '@nutui/nutui';
import '@nutui/nutui/dist/style.css';

const app = createApp(App);
app.use(NutUI);
app.mount('#app');

Use unplugin-vue-components to automatically import components as you use them.

  1. Install the plugin:
npm install unplugin-vue-components -D
  1. Configure vite.config.js:
import Components from 'unplugin-vue-components/vite';
import NutUIResolver from '@nutui/nutui/dist/resolvers';

export default {
  plugins: [
    Components({
      resolvers: [NutUIResolver()],
    }),
  ],
};

Now you can use NutUI components directly in your templates without importing them manually.


#Theme Customization

NutUI uses SCSS variables for theming. You can override them by creating a custom SCSS file.

  1. Create a file, e.g., src/styles/nutui-theme.scss:
// Custom primary color
$primary-color: #ff6600;
$primary-color-end: #ff8533;

// Button styles
$button-primary-background-color: $primary-color;
$button-primary-border-color: $primary-color;
  1. Import this file before NutUI styles in your main.js:
import './styles/nutui-theme.scss';
import '@nutui/nutui/dist/style.css';

#Common Components

#Button

<template>
  <div class="demo">
    <nut-button type="primary">Primary Button</nut-button>
    <nut-button type="success">Success Button</nut-button>
    <nut-button type="danger">Danger Button</nut-button>
    <nut-button plain>Plain Button</nut-button>
    <nut-button disabled>Disabled</nut-button>
  </div>
</template>

<script setup>
// No import needed when using on-demand
</script>

#Cell (List Item)

<template>
  <nut-cell-group>
    <nut-cell title="Title" desc="Description" is-link></nut-cell>
    <nut-cell title="With Icon">
      <template #icon>
        <nut-icon name="star"></nut-icon>
      </template>
    </nut-cell>
    <nut-cell title="Custom Slot">
      <template #link>
        <span>Custom content</span>
      </template>
    </nut-cell>
  </nut-cell-group>
</template>
<template>
  <div>
    <nut-button @click="showPopup = true">Open Popup</nut-button>
    <nut-popup v-model:visible="showPopup" position="bottom" :style="{ height: '200px' }">
      <div class="popup-content">Popup content</div>
    </nut-popup>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const showPopup = ref(false);
</script>

<style scoped>
.popup-content {
  padding: 20px;
  text-align: center;
}
</style>

#Toast

<template>
  <nut-button @click="showToast">Show Toast</nut-button>
</template>

<script setup>
import { showToast } from '@nutui/nutui';

const showToast = () => {
  showToast.text('Operation successful', {
    duration: 2000,
    position: 'center',
  });
};
</script>

#Dialog

<template>
  <nut-button @click="showDialog">Open Dialog</nut-button>
</template>

<script setup>
import { showDialog } from '@nutui/nutui';

const showDialog = () => {
  showDialog({
    title: 'Confirm',
    content: 'Are you sure you want to proceed?',
    onConfirm: () => {
      console.log('Confirmed');
    },
    onCancel: () => {
      console.log('Cancelled');
    },
  });
};
</script>

#Form Components

#Input

<template>
  <nut-form>
    <nut-form-item label="Username">
      <nut-input v-model="username" placeholder="Enter username" />
    </nut-form-item>
    <nut-form-item label="Password">
      <nut-input v-model="password" type="password" placeholder="Enter password" />
    </nut-form-item>
    <nut-button type="primary" block @click="handleSubmit">Submit</nut-button>
  </nut-form>
</template>

<script setup>
import { ref } from 'vue';

const username = ref('');
const password = ref('');

const handleSubmit = () => {
  console.log({ username: username.value, password: password.value });
};
</script>

#Radio

<template>
  <nut-radio-group v-model="selected">
    <nut-radio label="1">Option 1</nut-radio>
    <nut-radio label="2">Option 2</nut-radio>
    <nut-radio label="3">Option 3</nut-radio>
  </nut-radio-group>
</template>

<script setup>
import { ref } from 'vue';

const selected = ref('1');
</script>

#Checkbox

<template>
  <nut-checkbox-group v-model="checkedList">
    <nut-checkbox label="1">Option 1</nut-checkbox>
    <nut-checkbox label="2">Option 2</nut-checkbox>
    <nut-checkbox label="3">Option 3</nut-checkbox>
  </nut-checkbox-group>
</template>

<script setup>
import { ref } from 'vue';

const checkedList = ref(['1', '2']);
</script>

#Layout Components

#Grid

<template>
  <nut-grid :columns="3" :gap="10">
    <nut-grid-item>
      <nut-icon name="home" />
      <span>Home</span>
    </nut-grid-item>
    <nut-grid-item>
      <nut-icon name="star" />
      <span>Star</span>
    </nut-grid-item>
    <nut-grid-item>
      <nut-icon name="cart" />
      <span>Cart</span>
    </nut-grid-item>
  </nut-grid>
</template>

#Tabs

<template>
  <nut-tabs v-model="activeTab">
    <nut-tab-pane title="Tab 1">Content 1</nut-tab-pane>
    <nut-tab-pane title="Tab 2">Content 2</nut-tab-pane>
    <nut-tab-pane title="Tab 3">Content 3</nut-tab-pane>
  </nut-tabs>
</template>

<script setup>
import { ref } from 'vue';

const activeTab = ref(0);
</script>

#Tabbar

<template>
  <nut-tabbar v-model="activeTab">
    <nut-tabbar-item tab-key="home" icon="home">Home</nut-tabbar-item>
    <nut-tabbar-item tab-key="category" icon="category">Category</nut-tabbar-item>
    <nut-tabbar-item tab-key="cart" icon="cart">Cart</nut-tabbar-item>
    <nut-tabbar-item tab-key="user" icon="user">Profile</nut-tabbar-item>
  </nut-tabbar>
</template>

<script setup>
import { ref } from 'vue';

const activeTab = ref('home');
</script>

#Data Display Components

#Swiper

<template>
  <nut-swiper :autoplay="3000" :height="200">
    <nut-swiper-item v-for="item in list" :key="item">
      <img :src="item" style="width: 100%; height: 100%; object-fit: cover" />
    </nut-swiper-item>
  </nut-swiper>
</template>

<script setup>
const list = [
  'https://via.placeholder.com/400x200?text=Slide+1',
  'https://via.placeholder.com/400x200?text=Slide+2',
  'https://via.placeholder.com/400x200?text=Slide+3',
];
</script>

#Badge

<template>
  <nut-badge value="99+" dot>
    <nut-icon name="message" size="24px" />
  </nut-badge>
</template>

#Feedback Components

#Loading

<template>
  <nut-loading type="circular" />
  <nut-loading type="spinner" />
  <nut-loading type="dots" />
</template>

#Progress

<template>
  <nut-progress :percentage="70" color="#ff6600" />
</template>

#Integration with Vue Router

NutUI components work seamlessly with Vue Router. For example, you can use nut-tabbar with router links:

<template>
  <nut-tabbar v-model="activeTab" router>
    <nut-tabbar-item to="/home" tab-key="home" icon="home">Home</nut-tabbar-item>
    <nut-tabbar-item to="/category" tab-key="category" icon="category">Category</nut-tabbar-item>
    <nut-tabbar-item to="/cart" tab-key="cart" icon="cart">Cart</nut-tabbar-item>
    <nut-tabbar-item to="/user" tab-key="user" icon="user">Profile</nut-tabbar-item>
  </nut-tabbar>
</template>

#Internationalization

NutUI supports multiple languages. To change the language, import the desired locale:

import { createApp } from 'vue';
import App from './App.vue';
import NutUI from '@nutui/nutui';
import '@nutui/nutui/dist/style.css';
import enUS from '@nutui/nutui/dist/locale/en-US';

const app = createApp(App);
app.use(NutUI, { locale: enUS });
app.mount('#app');

#Best Practices

  • Use on‑demand import with unplugin-vue-components to keep bundle size minimal.
  • Override SCSS variables early to maintain consistent branding.
  • Combine NutUI with Pinia for state management in larger apps.
  • Test on both iOS and Android devices to ensure component behavior matches expected.
  • Refer to the official NutUI documentation for the latest updates and advanced usage.

#Troubleshooting

#Common Issues

  1. Styles not loading: Ensure you’ve imported @nutui/nutui/dist/style.css or the custom theme file.
  2. Component not found: If using on‑demand, verify the resolver is correctly set up. Otherwise, import components explicitly.
  3. Icon not displaying: Make sure you have the icon font assets included. NutUI uses icon fonts; you may need to copy the font files or use a CDN.

For more details, visit the GitHub repository or the official site.

Share this post