Browse Source

fix: navbar

“liqiong-lab” 5 years ago
parent
commit
d56a9340dd
5 changed files with 332 additions and 73 deletions
  1. 1 1
      src/config.ts
  2. 126 11
      src/packages/navbar/demo.vue
  3. 39 16
      src/packages/navbar/doc.md
  4. 56 13
      src/packages/navbar/index.scss
  5. 110 32
      src/packages/navbar/index.vue

+ 1 - 1
src/config.ts

@@ -56,7 +56,7 @@ export const nav = [
     packages: [
       {
         name: 'BackTop',
-        sort: '1',
+        sort: 1,
         cName: '回到顶部',
         type: 'component',
         show: true,

+ 126 - 11
src/packages/navbar/demo.vue

@@ -1,27 +1,142 @@
 <template>
   <div class="demo">
     <h2>基础用法</h2>
-    <nut-navbar leftShow title="订单详情" icon="share"></nut-navbar>
-    <nut-navbar leftShow title="浏览记录" desc="清空"></nut-navbar>
-    <!-- 是否支持自定义属性titIcon -->
-    <nut-navbar :leftShow="false" title="购物车" titIcon="locationg3" desc="编辑" icon="more"></nut-navbar>
+    <nut-navbar @on-click-back="back" @on-click-title="title" @on-click-send="send" title="订单详情" icon="share"></nut-navbar>
+    <nut-navbar @on-click-back="back" @on-click-title="title" @on-click-clear="clear" title="浏览记录" desc="清空"></nut-navbar>
+    <nut-navbar
+      :leftShow="false"
+      @on-click-title="title"
+      @on-click-icon="icon"
+      @on-click-clear="edit"
+      @on-click-send="more"
+      title="购物车"
+      titIcon="locationg3"
+      desc="编辑"
+      icon="nut-icon-more1"
+    ></nut-navbar>
+
     <h2>增加tab及右侧按钮</h2>
-    <nut-navbar title="商品" desc="编辑" icon="horizontal"></nut-navbar>
+    <nut-navbar
+      tab
+      :tabs="[
+        {
+          id: '11',
+          name: '商品'
+        },
+        {
+          id: '22',
+          name: '店铺'
+        }
+      ]"
+      @switch-tab="switchTab"
+      @on-click-back="back"
+      @on-click-title="title"
+      @on-click-clear="edit"
+      @on-click-send="list"
+      desc="编辑"
+      icon="horizontal"
+    >
+    </nut-navbar>
+
     <h2>多tab切换导航</h2>
-    <nut-navbar title="商品" icon="more"></nut-navbar>
+    <nut-navbar :tabs="tabList" @switch-tab="switchTab" @on-click-back="back" icon="share" @on-click-send="send">
+      <template #icons>
+        <nut-icon class="icon" name="nut-icon-more1" @on-click-slot-send="morelist"></nut-icon>
+      </template>
+    </nut-navbar>
   </div>
 </template>
 
 <script lang="ts">
+import { reactive } from 'vue';
 import { createComponent } from '@/utils/create';
 const { createDemo } = createComponent('navbar');
 export default createDemo({
-  props: {},
-  setup() {
-    const testClick = (event: Event) => {
-      alert(event);
+  setup(props, { emit }) {
+    const tabList = [
+      {
+        id: '11',
+        name: '商品'
+      },
+      {
+        id: '22',
+        name: '评价'
+      },
+      {
+        id: '33',
+        name: '详情'
+      },
+      {
+        id: '44',
+        name: '推荐'
+      },
+      {
+        id: '55',
+        name: '商品'
+      },
+      {
+        id: '66',
+        name: '评价'
+      },
+      {
+        id: '77',
+        name: '详情'
+      },
+      {
+        id: '88',
+        name: '推荐'
+      }
+    ];
+    const back = () => {
+      alert('header头部, 点击返回');
+    };
+    const title = () => {
+      alert('header头部, 点击title');
+    };
+    const right = () => {
+      alert('header头部, 点击右侧按钮');
+    };
+    const icon = () => {
+      alert('icon');
+    };
+    const send = () => {
+      alert('发送');
+    };
+    const edit = () => {
+      alert('编辑');
+    };
+    const more = () => {
+      alert('更多');
+    };
+    const clear = () => {
+      alert('清空');
+    };
+    const list = () => {
+      alert('列表');
+    };
+    const morelist = () => {
+      alert('多个更多');
+    };
+    function switchTab(id: number, name: string) {
+      console.log(id, name);
+    }
+
+    return {
+      back,
+      title,
+      right,
+      send,
+      edit,
+      clear,
+      more,
+      list,
+      icon,
+      morelist,
+      switchTab,
+      ...reactive({
+        tabList
+      })
     };
-    return { testClick };
   }
 });
 </script>

+ 39 - 16
src/packages/navbar/doc.md

@@ -22,30 +22,45 @@ app.use(Navbar);
 ### 基本用法
 
 ```html
-    <nut-navbar leftShow title="订单详情" icon="share"></nut-navbar>
-    <nut-navbar leftShow title="浏览记录" desc="清空"></nut-navbar>
-    <nut-navbar :leftShow="false" title="购物车" titIcon="locationg3" desc="编辑" icon="more"></nut-navbar>
+  <nut-navbar  @on-click-back="back" @on-click-title="title" @on-click-send="send" title="订单详情" icon="share"></nut-navbar>
+  <nut-navbar @on-click-back="back" @on-click-title="title" @on-click-clear="clear"  title="浏览记录" desc="清空"></nut-navbar>
+  <nut-navbar :leftShow="false" @on-click-title="title" @on-click-icon="icon" @on-click-clear="edit"  @on-click-send="more" title="购物车" titIcon="locationg3" desc="编辑" icon="more"></nut-navbar>
+
 ```
 
-### 增加tab及右侧按钮
+### 设置slot:tabs可以增加tab
 
 ```html
-    <nut-navbar title="商品" titIcon="locationg3" desc="编辑" icon="horizontal"></nut-navbar>
+    <nut-navbar @on-click-back="back" @on-click-title="title" @on-click-clear="edit" @on-click-send="list" desc="编辑" icon="horizontal">
+      <template v-slot:tabs>
+        <nut-tab>
+          <nut-tab-panel tab-title="商品"><p class="content">这里是页签全部内容</p></nut-tab-panel>
+          <nut-tab-panel tab-title="店铺"><p class="content">这里是页签待付款内容</p></nut-tab-panel>
+        </nut-tab>
+      </template>
+    </nut-navbar>
 ```
 
-### 多tab切换导航
+### 多tab切换导航及增加右侧按钮
 
 ```html
-    <nut-navbar title="商品" titIcon="locationg3" icon="more"></nut-navbar>
+    <nut-navbar @on-click-back="back" icon="share" @on-click-send="send">
+      <template v-slot:tabs>
+        <nut-tab>
+          <nut-tab-panel tab-title="商品"><p class="content">这里是页签全部内容</p></nut-tab-panel>
+          <nut-tab-panel tab-title="评价"><p class="content">这里是页签待付款内容</p></nut-tab-panel>
+          <nut-tab-panel tab-title="详情"><p class="content">这里是页签待付款内容</p></nut-tab-panel>
+          <nut-tab-panel tab-title="推荐"><p class="content">这里是页签待付款内容</p></nut-tab-panel>
+        </nut-tab>
+      </template>
+
+      <template #icons >
+        <nut-icon class="icon" name="more" @on-click-slot-send="morelist"></nut-icon>
+      </template>
+    </nut-navbar>
 ```
 
-### 链接
-
-### 展示图标
-
-### API
-
-### Prop
+### Prop  
 
 | 字段            | 说明                                                                                           | 类型    | 默认值  |
 |-----------------|------------------------------------------------------------------------------------------------|---------|---------|
@@ -53,5 +68,13 @@ app.use(Navbar);
 | desc            | 右侧描述                                                                                       | String  | -       |
 | leftShow        | 是否展示左侧箭头                                                                              | Boolean | false   |
 | icon            | 左侧 [图标名称](#/icon) 或图片链接                                                             | String  | -       |
-
-### Event
+| titIcon         | 标题带icon                                                         | String  | -       |                                          
+
+### Event
+| 名称  | 说明     | 回调参数    |
+|-------|----------|-------------|
+| back | 点击返回上一页事件 | event:Event |
+| title | 点击页面标题事件 | event:Event |
+| right | 点击右侧按钮事件 | event:Event |
+| back | 点击返回上一页事件 | event:Event |
+| back | 点击返回上一页事件 | event:Event |

+ 56 - 13
src/packages/navbar/index.scss

@@ -1,10 +1,14 @@
+#app .demo {
+  padding: 0 0;
+  padding-top: 57px;
+}
+.demo > h2 {
+  margin-left: 15px;
+}
+
 .nut-navbar {
   position: relative;
-  display: -webkit-box;
-  display: -webkit-flex;
   display: flex;
-  -webkit-box-align: center;
-  -webkit-align-items: center;
   align-items: center;
   height: 44px;
   padding: 13px 16px;
@@ -12,7 +16,7 @@
   box-shadow: 0px 1px 7px 0px rgba(237, 238, 241, 1);
   font-size: $cell-title-font;
   color: $cell-color;
-  margin: 10px 0;
+  margin-bottom: 20px;
   &:active::before {
     opacity: 0.1;
   }
@@ -20,6 +24,7 @@
     cursor: pointer;
     &::before {
       position: absolute;
+      content: ' ';
       top: 50%;
       left: 50%;
       width: 100%;
@@ -30,7 +35,6 @@
       border-radius: inherit;
       transform: translate(-50%, -50%);
       opacity: 0;
-      content: ' ';
     }
   }
 
@@ -41,42 +45,81 @@
   }
 
   &__title {
-    max-width: 60%;
+    min-width: 53%;
     margin: 0 auto;
+    text-align: center;
     &.icon {
       .icon {
-        margin-right: 10px;
         margin-left: 8px;
       }
     }
     &-desc {
       font-size: $cell-title-desc-font;
     }
+
+    .tab-title {
+      width: 170px;
+      white-space: nowrap;
+      overflow-x: auto;
+      display: flex;
+      .tab-title-box {
+        height: 50px;
+        display: flex;
+        flex: 1;
+        justify-content: center;
+        align-items: center;
+        box-sizing: border-box;
+        text-align: center;
+        font-size: 14px;
+        font-family: PingFangSC-Regular;
+        color: rgba(26, 26, 26, 1);
+        margin-left: 10px;
+      }
+      .nut-tab-active {
+        color: #1a1a1a;
+        font-weight: bold;
+        font-size: 16px;
+        position: relative;
+        &::after {
+          content: '';
+          position: absolute;
+          bottom: 7px;
+          left: 50%;
+          transform: translateX(-50%);
+          width: 12px;
+          height: 4px;
+          background-image: url('https://img12.360buyimg.com/imagetools/jfs/t1/127200/40/18747/536/5fb36b5aE61cac2d8/638032e8da9b93f4.png');
+          background-size: 100% 100%;
+        }
+      }
+    }
   }
+
+  &__title ::-webkit-scrollbar {
+    display: none;
+  }
+
   &__left {
     font-size: $cell-desc-font;
     color: $cell-desc-color;
     position: absolute;
+    left: 0;
     top: 0;
     bottom: 0;
     display: flex;
     align-items: center;
     cursor: pointer;
     padding: 0 16px;
-
-    left: 0;
   }
   &__right {
     font-size: $cell-desc-font;
     color: $cell-desc-color;
-
     position: absolute;
+    right: 0;
     top: 0;
     bottom: 0;
     display: flex;
     align-items: center;
-
-    right: 0;
     padding: 0 16px;
     cursor: pointer;
   }

+ 110 - 32
src/packages/navbar/index.vue

@@ -1,57 +1,135 @@
 <template>
-  <view :class="classes" @click="handleClick">
-    <slot>
-      <!-- 左侧  icon-->
-      <view class="nut-navbar__left">
-        <nut-icon v-if="leftShow" color="#979797" name="left"></nut-icon>
+  <view :class="classes">
+    <view class="nut-navbar__left">
+      <nut-icon v-if="leftShow" color="#979797" name="left" @click="handleLeft"></nut-icon>
+    </view>
+    <view class="nut-navbar__title" :class="{ icon: icon }" v-if="title || titIcon || tabs" ref="navlist">
+      <view v-if="title" @click="handleCenter">{{ title }}</view>
+      <nut-icon v-if="titIcon" class="icon" :name="titIcon" @click="handleCenterIcon"></nut-icon>
+      <view class="tab-title">
+        <view
+          :class="['tab-title-box', { 'nut-tab-active': activeIndex == item.id || activeIndex == index }]"
+          @click="switchTitle(item.id, item.name)"
+          v-for="(item, index) in tabs"
+          :key="index"
+        >
+          {{ item.name }}
+        </view>
       </view>
-
-      <view class="nut-navbar__title" :class="{ icon: icon }" v-if="title || titIcon">
-        <view v-if="title">{{ title }}</view>
-        <nut-icon v-if="titIcon" class="icon" :name="titIcon"></nut-icon>
-      </view>
-
-      <!-- 右侧  title/icon/多个tit/多个icon-->
-      <view class="nut-navbar__right" :class="{ icon: icon }" v-if="desc || icon">
-        <view v-if="desc" :style="{ 'text-align': descTextAlign }">{{ desc }}</view>
-        <view> <nut-icon v-if="icon" class="icon" :name="icon"></nut-icon></view>
-      </view>
-    </slot>
+    </view>
+    <view class="nut-navbar__right" :class="{ icon: icon }" v-if="desc || icon">
+      <view v-if="desc" :style="{ 'text-align': descTextAlign }" @click="handleClear">{{ desc }}</view>
+      <view> <nut-icon v-if="icon" class="icon" :name="icon" @click="handleSend"></nut-icon></view>
+      <template v-if="icon">
+        <view @click="handleSends"><slot name="icons"></slot></view>
+      </template>
+    </view>
   </view>
 </template>
 
 <script lang="ts">
-import { computed } from 'vue';
+import { computed, ref } from 'vue';
 import { createComponent } from '@/utils/create';
 import { useRouter } from 'vue-router';
-import Icon from '@/packages/icon/index.vue';
 const { componentName, create } = createComponent('navbar');
 
 export default create({
   props: {
-    title: { type: String, default: '' },
-    leftShow: { type: Boolean, default: true },
-    icon: { type: String, default: '' },
-    desc: { type: String, default: '' },
-    titIcon: { type: String, default: '' }
-  },
-  components: {
-    [Icon.name]: Icon
+    leftShow: { type: Boolean, default: true }, //左侧  是否显示返回
+    title: { type: String, default: '' }, //中间  文字标题
+    titIcon: { type: String, default: '' }, //中间  标题icon
+    tabs: {
+      type: Array,
+      defaul: () => {
+        return [];
+      }
+    },
+    icon: { type: String, default: '' }, //右侧   按钮图标
+    desc: { type: String, default: '' }, //右侧   按钮文字
+
+    defaultIndex: {
+      type: Number,
+      default: 0
+    }
   },
-  emits: ['click'],
+  emits: [
+    'click',
+    'on-click-back',
+    'on-click-title',
+    'on-click-right',
+    'on-click-desc',
+    'on-click-icon',
+    'on-click-more',
+    'on-click-clear',
+    'on-click-send',
+    'on-click-slot',
+    'on-click-slot-send',
+    'switch-tab'
+  ],
   setup(props, { emit }) {
+    const { tabs } = props;
+    const activeIndex = ref(props.defaultIndex);
     const classes = computed(() => {
       const prefixCls = componentName;
       return {
-        [prefixCls]: true,
-        [`${prefixCls}--clickable`]: props.leftShow
+        [prefixCls]: true
       };
     });
     const router = useRouter();
 
+    function switchTitle(id: number, name: string) {
+      activeIndex.value = id;
+      console.log(id);
+      emit('switch-tab', activeIndex.value, name);
+    }
+
+    function handleLeft() {
+      emit('on-click-back');
+    }
+
+    function handleCenter() {
+      emit('on-click-title');
+    }
+    function handleCenterIcon() {
+      emit('on-click-icon');
+    }
+
+    function handleClear() {
+      emit('on-click-clear');
+    }
+
+    function handleRight() {
+      emit('on-click-right');
+    }
+    function handleMore() {
+      emit('on-click-more');
+    }
+
+    function handleSend() {
+      emit('on-click-send');
+    }
+
+    function handleSlot() {
+      emit('on-click-slot');
+    }
+
+    function handleSends() {
+      emit('on-click-slot-send');
+    }
+
     return {
-      //handleClick,
-      classes
+      classes,
+      handleLeft,
+      handleCenter,
+      handleCenterIcon,
+      handleRight,
+      handleClear,
+      handleSend,
+      handleSlot,
+      handleSends,
+      tabs,
+      switchTitle,
+      activeIndex
     };
   }
 });