The href attribute of the a tag and the event modifier prevent the default behavior

Tell me about the problems you encountered

  1. In the screenshot below, when I click on the first-level, second-level and third-level categories in the left navigation bar, I will jump to the Search page, but when I trigger the click event to jump, I always cannot jump normally, and will jump Go to the home page, and then click the back button of the browser to return to the search page.
    insert image description here
  2. This is the address I want to jump toinsert image description here
  3. However, it always jumps to the home page

the code

<template>
  <!-- 商品分类导航 -->
  <div class="type-nav">
    <div class="container">
      <!-- 事件委派 -->
      <div @mouseleave="leaveIndex" @click.prevent="goSearch">
        <h2 class="all">全部商品分类</h2>
        <div class="sort">
          <div class="all-sort-list2">
            <div
              class="item"
              v-for="(item, index) in categoryList"
              :key="item.categoryId"
              :class="{ bo: currentIndex == index }"
            >
              <h3 @mouseenter="changeIndex(index)">
                <a href="" :data-categoryName="item.categoryName" :data-category1Id="item.categoryId">{
    
    {
    
     item.categoryName }}</a>
              </h3>
              <!-- 二级、三级分类 -->
              <div
                class="item-list clearfix"
                :style="{ display: currentIndex == index ? 'block' : 'none' }"
              >
                <div
                  class="subitem"
                  v-for="subitem in item.categoryChild"
                  :key="subitem.categoryId"
                >
                  <dl class="fore">
                    <dt>
                      <a href="" :data-categoryName="subitem.categoryName" :data-category2Id="subitem.categoryId">{
    
    {
    
     subitem.categoryName }}</a>
                    </dt>
                    <dd>
                      <em
                        v-for="item3 in subitem.categoryChild"
                        :key="item3.categoryId"
                      >
                        <a href="" :data-categoryName="item3.categoryName" :data-category3Id="item3.categoryId">{
    
    {
    
     item3.categoryName }}</a>
                      </em>
                    </dd>
                  </dl>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <nav class="nav">
        <a href="###">服装城</a>
        <a href="###">美妆馆</a>
        <a href="###">尚品汇超市</a>
        <a href="###">全球购</a>
        <a href="###">闪购</a>
        <a href="###">团购</a>
        <a href="###">有趣</a>
        <a href="###">秒杀</a>
      </nav>
    </div>
  </div>
</template>

<script>
import {
    
     mapState } from "vuex";
// 引入第三方插件使用节流
import throttle from "lodash/throttle";
export default {
    
    
  name: "TypeNav",
  data() {
    
    
    return {
    
    
      // 鼠标滑过的一级菜单的index,切记初始值不能为0
      currentIndex: -1,
    };
  },
  mounted() {
    
    
    // 分发action,通知vuex,可以向服务器发送请求,获取数据,存取在仓库当中
    this.$store.dispatch("categoryList");
  },
  computed: {
    
    
    // 预测需要是一个函数,当这个计算属性使用时,这个函数就执行一次
    // 会注入一个state,这个state就是大仓库中的state
    ...mapState({
    
    
      categoryList: (state) => state.home.categoryList,
    }),
  },
  methods: {
    
    
    // 鼠标进入修改响应式数据currentIndex的值
    // 节流:用户操作很频繁,但是把频繁的操作变成少量的的操作,【可以给浏览器有充裕的时间解析代码】
    // 防抖:用户操作很频繁,只执行最后一次
    changeIndex: throttle(function (index) {
    
    
      this.currentIndex = index;
    }, 50),
    leaveIndex() {
    
    
      this.currentIndex = -1;
    },
    //精益求精
    //将全部的子节点的事件委派给父节点->事件回调就一个
    goSearch(event) {
    
    
      //第一个问题:div父节点子元素太多【h3、h2、em、dt、dd、dl...a】?你怎么知道你点击的一定是a
      //第二个问题:要区分一级分类、二级分类、三级分类的a标签【category1Id|category2Id|category2Id】
      let targetNode = event.target;
      //获取触发事件节点的自定义属性【a:data-categoryName】
      let {
    
     categoryname, category1id, category2id, category3id } =
        targetNode.dataset;
      //判断点击的是a【不管是1|2|3】
      if (categoryname) {
    
    
        //点击只要是a,就是往search模块跳转
        var locations = {
    
    
          name: "search",
          query: {
    
     categoryName: categoryname },
        };
        //一级分类的a
        if (category1id) {
    
    
          console.log("category1id-------", category1id);
          locations.query.category1Id = category1id;
        } else if (category2id) {
    
    
          //二级分类的a
          locations.query.category2Id = category2id;
        } else {
    
    
          //三级分类的a
          locations.query.category3Id = category3id;
        }
        //点击商品分类按钮的时候,如果路径当中携带params参数,需要合并携带给search模块
        if (this.$route.params.keyword) {
    
    
          locations.params = this.$route.params;
        }
        //目前商品分类这里携带参数只有query参数
        this.$router.push(locations);
      }
    },
  },
};
</script>

<style lang="less" scoped>
.type-nav {
    
    
  border-bottom: 2px solid #e1251b;

  .container {
    
    
    width: 1200px;
    margin: 0 auto;
    display: flex;
    position: relative;

    .all {
    
    
      width: 210px;
      height: 45px;
      background-color: #e1251b;
      line-height: 45px;
      text-align: center;
      color: #fff;
      font-size: 14px;
      font-weight: bold;
    }

    .nav {
    
    
      a {
    
    
        height: 45px;
        margin: 0 22px;
        line-height: 45px;
        font-size: 16px;
        color: #333;
      }
    }

    .sort {
    
    
      position: absolute;
      left: 0;
      top: 45px;
      width: 210px;
      height: 461px;
      position: absolute;
      background: #fafafa;
      z-index: 999;

      .all-sort-list2 {
    
    
        .item {
    
    
          h3 {
    
    
            line-height: 30px;
            font-size: 14px;
            font-weight: 400;
            overflow: hidden;
            padding: 0 20px;
            margin: 0;

            a {
    
    
              color: #333;
            }
          }

          .item-list {
    
    
            display: none;
            position: absolute;
            width: 734px;
            min-height: 460px;
            background: #f7f7f7;
            left: 210px;
            border: 1px solid #ddd;
            top: 0;
            z-index: 9999 !important;

            .subitem {
    
    
              float: left;
              width: 650px;
              padding: 0 4px 0 8px;

              dl {
    
    
                border-top: 1px solid #eee;
                padding: 6px 0;
                overflow: hidden;
                zoom: 1;

                &.fore {
    
    
                  border-top: 0;
                }

                dt {
    
    
                  float: left;
                  width: 54px;
                  line-height: 22px;
                  text-align: right;
                  padding: 3px 6px 0 0;
                  font-weight: 700;
                }

                dd {
    
    
                  float: left;
                  width: 415px;
                  padding: 3px 0 0;
                  overflow: hidden;

                  em {
    
    
                    float: left;
                    height: 14px;
                    line-height: 14px;
                    padding: 0 8px;
                    margin-top: 5px;
                    border-left: 1px solid #ccc;
                  }
                }
              }
            }
          }
        }
        .bo {
    
    
          background-color: skyblue;
        }
      }
    }
  }
}
</style>

Below is my routing configuration file

// 配置路由, 一定要注意这里是routes,不是routers
    routes: [ 
        {
    
    
            path: '/home',
            component: Home,
            meta: {
    
    
                show: true
            }
        },
        {
    
    
            path: '/login',
            name: 'login',
            component: Login,
            meta: {
    
    
                show: false
            }
        },
        {
    
    
            // 注意占位符是:开头,占位符后面加上一个问号,可传可不传
            path: '/search/:keyword?',
            name: 'search',
            component: Search,
            meta: {
    
    
                show: true
            }
        },
        {
    
    
            path: '/register',
            component: Regsiter,
            meta: {
    
    
                show: false
            }
        },
        {
    
    
            path: '/',
            redirect: '/home'
        }
    ]

problem analysis

  1. First of all, my above goSearch method uses the method of event delegation. The a label is determined through the custom attribute categoryname, and the 1|2|3 level classification is determined through the custom attribute categoryid.
  2. Because my click event is triggered by the a tag, and there is an empty href attribute on my a tag, so the b tag will have a default behavior according to the empty link address, to jump
  3. It happened that I also configured routing redirection, and he followed the last redirection to jump to the home page. I clicked the browser back button and returned to the address redirected by the gosearch method.

Solution

  • One is to remove the href attribute of the a tag
  • The second is to add a prevent event modifier to the click event to prevent the default behavior
  • The third is to call preventDefault() or e.returnValue = false; to prevent the default behavior
  • Of course, you can also use the a tag here

Supplement other event modifiers

.capture: Capture bubbling, that is, when bubbling occurs, the dom element with this modifier will be executed first. If there are more than one, they will be executed sequentially from outside to inside, and then the triggered events will be executed in natural order.

.self: Bind the event to itself, which can only be triggered by itself, usually used to avoid the influence of bubbling events

.once: The setting event can only be triggered once, such as button click, etc.

.passive: This modifier probably means to optimize the performance of DOM's default events, according to the examples on the official website, such as scrolling beyond the maximum range.

. native: Binding a native event to the child component in the parent component turns the child component into a normal HTML tag, which cannot be triggered without the '. native' event.
.stop: prevent bubbling
.stop.prevent: concatenation modifier

Guess you like

Origin blog.csdn.net/m0_56026872/article/details/127067557