Skip to content

组件组合使用示例

展示多个组件组合使用的实际场景。

搜索表单 + 数据表格

最常见的组合:搜索表单配合数据表格展示。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>搜索表单 + 表格示例</title>
  <link rel="stylesheet" href="./sanoui.min.css">
</head>
<body>
  <div style="padding: 20px;">
    <!-- 搜索表单 -->
    <div style="padding: 16px; background: #f5f7fa; border-radius: 8px; margin-bottom: 16px;">
      <div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
        <div class="sa-input" 
             id="search-input"
             data-placeholder="请输入关键词" 
             data-prefix-icon="search"
             style="flex: 1; min-width: 200px; max-width: 300px;">
        </div>
        
        <div class="sa-select" 
             id="status-select"
             data-select
             data-placeholder="全部状态"
             data-options='[{"label":"全部","value":""},{"label":"启用","value":"1"},{"label":"禁用","value":"0"}]'
             style="width: 150px;">
        </div>
        
        <div class="sa-date-picker" 
             id="date-picker"
             data-date-picker
             data-placeholder="选择日期"
             style="width: 150px;">
        </div>
        
        <button class="sa-button" 
                id="search-btn"
                data-button 
                data-type="primary"
                data-icon="search">
          搜索
        </button>
        
        <button class="sa-button" 
                id="reset-btn"
                data-button>
          重置
        </button>
      </div>
    </div>
    
    <!-- 表格 -->
    <div id="data-table" style="height: 400px;"></div>
    
    <!-- 分页 -->
    <div id="pagination" style="margin-top: 16px;"></div>
  </div>
  
  <script src="./sanoui.min.js"></script>
  <script>
    // 初始化所有组件
    const page = SA.init('body');
    
    // 获取组件实例
    const searchInput = page.get('#search-input');
    const statusSelect = page.get('#status-select');
    const datePicker = page.get('#date-picker');
    const searchBtn = page.get('#search-btn');
    const resetBtn = page.get('#reset-btn');
    
    // 创建表格
    const table = new SaTable('#data-table', {
      columns: [
        { prop: 'name', label: '姓名', width: 120 },
        { prop: 'status', label: '状态', width: 100 },
        { prop: 'email', label: '邮箱', width: 200 },
        { prop: 'date', label: '日期', width: 150 }
      ],
      data: []
    });
    
    // 创建分页
    let currentPage = 1;
    const pageSize = 10;
    
    const pagination = new SaPagination('#pagination', {
      total: 0,
      pageSize: pageSize,
      current: currentPage,
      layout: 'total, prev, pager, next, jumper',
      onChange: (page, size) => {
        currentPage = page;
        loadData();
      }
    });
    
    // 加载数据
    function loadData() {
      const keyword = searchInput ? searchInput.getValue() : '';
      const status = statusSelect ? statusSelect.getValue() : '';
      const date = datePicker ? datePicker.getValue() : '';
      
      // 模拟数据加载
      const data = Array.from({ length: pageSize }, (_, i) => ({
        id: (currentPage - 1) * pageSize + i + 1,
        name: keyword ? `${keyword}${i + 1}` : `用户${(currentPage - 1) * pageSize + i + 1}`,
        status: status || (i % 2 === 0 ? '启用' : '禁用'),
        email: `user${(currentPage - 1) * pageSize + i + 1}@example.com`,
        date: date || '2024-12-25'
      }));
      
      table.setData(data);
      pagination.setTotal(100);
    }
    
    // 搜索按钮点击
    if (searchBtn) {
      searchBtn.onClick = () => {
        currentPage = 1;
        pagination.setCurrent(1);
        loadData();
      };
    }
    
    // 重置按钮点击
    if (resetBtn) {
      resetBtn.onClick = () => {
        if (searchInput) searchInput.setValue('');
        if (statusSelect) statusSelect.setValue('');
        if (datePicker) datePicker.clear();
        currentPage = 1;
        pagination.setCurrent(1);
        loadData();
      };
    }
    
    // 初始化加载
    loadData();
  </script>
</body>
</html>

表单 + 对话框

在对话框中嵌入表单的常见场景。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>表单对话框示例</title>
  <link rel="stylesheet" href="./sanoui.min.css">
</head>
<body>
  <div style="padding: 20px;">
    <button class="sa-button" 
            id="open-dialog-btn"
            data-button 
            data-type="primary">
      打开表单对话框
    </button>
  </div>
  
  <script src="./sanoui.min.js"></script>
  <script>
    SA.init('body');
    
    const openBtn = document.getElementById('open-dialog-btn');
    
    openBtn.addEventListener('click', () => {
      // 创建对话框内容
      const formContent = document.createElement('div');
      formContent.innerHTML = `
        <form class="sa-form" id="dialog-form" style="padding: 20px;">
          <div class="sa-form-item">
            <label class="sa-form-item__label">用户名</label>
            <div class="sa-form-item__content">
              <div class="sa-input" 
                   data-prop="username"
                   data-placeholder="请输入用户名"
                   data-clearable="true"></div>
            </div>
          </div>
          <div class="sa-form-item">
            <label class="sa-form-item__label">邮箱</label>
            <div class="sa-form-item__content">
              <div class="sa-input" 
                   data-prop="email"
                   data-placeholder="请输入邮箱"
                   data-type="email"></div>
            </div>
          </div>
        </form>
      `;
      
      // 创建对话框
      const dialog = new SaDialog({
        title: '用户信息',
        content: formContent,
        width: '500px',
        onConfirm: () => {
          const form = new SaForm('#dialog-form', {
            rules: {
              username: [{ required: true, message: '请输入用户名' }],
              email: [
                { required: true, message: '请输入邮箱' },
                { type: 'email', message: '请输入正确的邮箱格式' }
              ]
            }
          });
          
          form.validate().then(valid => {
            if (valid) {
              const values = form.getValues();
              console.log('表单数据:', values);
              dialog.close();
            }
          });
        }
      });
      
      dialog.open();
      
      // 初始化表单中的组件
      setTimeout(() => {
        SA.init('#dialog-form');
      }, 100);
    });
  </script>
</body>
</html>

表格 + 操作按钮

表格配合操作按钮的组合使用。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>表格操作示例</title>
  <link rel="stylesheet" href="./sanoui.min.css">
</head>
<body>
  <div style="padding: 20px;">
    <!-- 操作栏 -->
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
      <div style="display: flex; gap: 10px;">
        <button class="sa-button" 
                id="add-btn"
                data-button 
                data-type="primary"
                data-icon="plus">
          新增
        </button>
        <button class="sa-button" 
                id="edit-btn"
                data-button>
          编辑
        </button>
        <button class="sa-button" 
                id="delete-btn"
                data-button 
                data-type="danger"
                data-icon="delete">
          删除
        </button>
      </div>
      
      <div class="sa-input" 
           id="search-input"
           data-placeholder="搜索..." 
           data-prefix-icon="search"
           style="width: 300px;">
      </div>
    </div>
    
    <!-- 表格 -->
    <div id="operation-table" style="height: 400px;"></div>
  </div>
  
  <script src="./sanoui.min.js"></script>
  <script>
    SA.init('body');
    
    const page = SA.init('body');
    const searchInput = page.get('#search-input');
    const addBtn = page.get('#add-btn');
    const editBtn = page.get('#edit-btn');
    const deleteBtn = page.get('#delete-btn');
    
    // 创建表格
    const table = new SaTable('#operation-table', {
      columns: [
        { prop: 'name', label: '姓名', width: 120 },
        { prop: 'age', label: '年龄', width: 100 },
        { prop: 'email', label: '邮箱', width: 200 },
        {
          prop: 'actions',
          label: '操作',
          width: 200,
          render: (row) => {
            return `
              <button class="sa-button sa-button--primary sa-button--small" data-action="edit" data-id="${row.id}">编辑</button>
              <button class="sa-button sa-button--danger sa-button--small" data-action="delete" data-id="${row.id}">删除</button>
            `;
          }
        }
      ],
      data: [
        { id: 1, name: '张三', age: 25, email: 'zhangsan@example.com' },
        { id: 2, name: '李四', age: 30, email: 'lisi@example.com' },
        { id: 3, name: '王五', age: 28, email: 'wangwu@example.com' }
      ]
    });
    
    // 新增按钮
    if (addBtn) {
      addBtn.onClick = () => {
        SaDialog.alert({
          title: '提示',
          content: '打开新增对话框'
        });
      };
    }
    
    // 编辑按钮
    if (editBtn) {
      editBtn.onClick = () => {
        const selectedRows = table.getSelectedRows();
        if (selectedRows.length === 0) {
          SaMessage.warning('请先选择一行数据');
          return;
        }
        SaDialog.alert({
          title: '提示',
          content: `编辑: ${selectedRows[0].name}`
        });
      };
    }
    
    // 删除按钮
    if (deleteBtn) {
      deleteBtn.onClick = () => {
        const selectedRows = table.getSelectedRows();
        if (selectedRows.length === 0) {
          SaMessage.warning('请先选择要删除的数据');
          return;
        }
        
        SaDialog.confirm({
          title: '确认删除',
          content: `确定要删除选中的 ${selectedRows.length} 条数据吗?`
        }).then(() => {
          SaMessage.success('删除成功');
          // 执行删除操作
        });
      };
    }
    
    // 搜索
    if (searchInput) {
      searchInput.onChange = (value) => {
        console.log('搜索:', value);
        // 执行搜索
      };
    }
  </script>
</body>
</html>

表单 + 标签页

使用标签页组织多个表单。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>表单标签页示例</title>
  <link rel="stylesheet" href="./sanoui.min.css">
</head>
<body>
  <div style="padding: 20px;">
    <div class="sa-tabs" id="form-tabs">
      <div class="sa-tabs__header">
        <div class="sa-tabs__item sa-tabs__item--active" data-tab="basic">基本信息</div>
        <div class="sa-tabs__item" data-tab="detail">详细信息</div>
        <div class="sa-tabs__item" data-tab="setting">设置</div>
      </div>
      <div class="sa-tabs__content">
        <!-- 基本信息表单 -->
        <div class="sa-tabs__panel" data-tab="basic">
          <form class="sa-form" id="basic-form" style="margin-top: 20px;">
            <div class="sa-form-item">
              <label class="sa-form-item__label">用户名</label>
              <div class="sa-form-item__content">
                <div class="sa-input" data-prop="username" data-placeholder="请输入用户名"></div>
              </div>
            </div>
            <div class="sa-form-item">
              <label class="sa-form-item__label">邮箱</label>
              <div class="sa-form-item__content">
                <div class="sa-input" data-prop="email" data-type="email" data-placeholder="请输入邮箱"></div>
              </div>
            </div>
          </form>
        </div>
        
        <!-- 详细信息表单 -->
        <div class="sa-tabs__panel" data-tab="detail" style="display: none;">
          <form class="sa-form" id="detail-form" style="margin-top: 20px;">
            <div class="sa-form-item">
              <label class="sa-form-item__label">地址</label>
              <div class="sa-form-item__content">
                <div class="sa-input" data-prop="address" data-placeholder="请输入地址"></div>
              </div>
            </div>
            <div class="sa-form-item">
              <label class="sa-form-item__label">电话</label>
              <div class="sa-form-item__content">
                <div class="sa-input" data-prop="phone" data-placeholder="请输入电话"></div>
              </div>
            </div>
          </form>
        </div>
        
        <!-- 设置表单 -->
        <div class="sa-tabs__panel" data-tab="setting" style="display: none;">
          <form class="sa-form" id="setting-form" style="margin-top: 20px;">
            <div class="sa-form-item">
              <label class="sa-form-item__label">接收通知</label>
              <div class="sa-form-item__content">
                <div class="sa-switch" data-switch data-checked="true" data-labels='["关闭", "开启"]'></div>
              </div>
            </div>
            <div class="sa-form-item">
              <label class="sa-form-item__label">主题</label>
              <div class="sa-form-item__content">
                <div class="sa-select" 
                     data-select
                     data-options='[{"label":"浅色","value":"light"},{"label":"深色","value":"dark"}]'
                     style="width: 200px;">
                </div>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
    
    <div style="margin-top: 20px;">
      <button class="sa-button" data-button data-type="primary">保存</button>
    </div>
  </div>
  
  <script src="./sanoui.min.js"></script>
  <script>
    // 初始化所有组件
    SA.init('body');
    
    // 标签页切换
    const tabItems = document.querySelectorAll('.sa-tabs__item');
    const tabPanels = document.querySelectorAll('.sa-tabs__panel');
    
    tabItems.forEach(item => {
      item.addEventListener('click', () => {
        const tabName = item.getAttribute('data-tab');
        
        // 切换标签
        tabItems.forEach(i => i.classList.remove('sa-tabs__item--active'));
        item.classList.add('sa-tabs__item--active');
        
        // 切换面板
        tabPanels.forEach(p => p.style.display = 'none');
        document.querySelector(`.sa-tabs__panel[data-tab="${tabName}"]`).style.display = 'block';
      });
    });
  </script>
</body>
</html>

总结

以上示例展示了常见的组件组合使用场景:

  1. 搜索表单 + 数据表格 - 最常见的后台管理页面模式
  2. 表单 + 对话框 - 弹窗表单的常见场景
  3. 表格 + 操作按钮 - 数据列表的操作场景
  4. 表单 + 标签页 - 复杂表单的组织方式

通过这些组合示例,你可以了解到:

  • 如何让多个组件协同工作
  • 如何获取和管理组件实例
  • 如何处理组件间的事件通信
  • 如何组织复杂的页面结构

更多组合使用场景,可以参考实际项目需求进行扩展。

Released under the MIT License.