1. 程式人生 > 其它 >vue + vuetify + electron 實現ctrl+f的搜尋功能

vue + vuetify + electron 實現ctrl+f的搜尋功能

因為在electron 中沒有找到ctrl+f 呼叫瀏覽器搜尋的方法 於是借鑑文章自己擼了一個搜尋元件

借鑑文章地址:https://www.jb51.net/article/181616.htm

效果

模板部分

    <v-card class="history-info-drawer">
    <!-- 頭部操作欄 -->
      <v-toolbar dense dark color="primary">
        <!-- input -->
        <v-text-field
          type="text"
          hide-details
          prepend-icon="mdi-magnify"
          single-line
          clearable
          placeholder="請輸入要搜尋的字串 回車進行定位"
          v-model="searchStr"
          @keyup.enter="e => submit()"
        ></v-text-field>
        <!-- 上下按鈕 -->
        <v-btn icon @click="submit('up')">
          <v-icon>mdi-chevron-up</v-icon>
        </v-btn>
        <v-btn icon @click="submit('down')">
          <v-icon>mdi-chevron-down</v-icon>
        </v-btn>
        <!-- 關閉按鈕 -->
        <v-btn icon @click="$emit('input', false)">
          <v-icon>mdi-close</v-icon>
        </v-btn>
      </v-toolbar>
      <!-- 內容顯示區域 -->
      <v-card-text>
        <div v-html="transitionContent" class="history-info-content"></div>
      </v-card-text>
    </v-card>

邏輯部分

export default {
  name: "HistoryInfoDrawer",
  props: {
    // 傳入的內容字串
    content: {
      type: String,
      defualt: ""
    }
  },
  data() {
    return {
      //搜尋內容
      searchStr: "",
      // 搜尋定位
      currentPosition: 0,
      // 經過轉換的展示內容
      transitionContent: "",
      // 當前搜尋字串是否是首次定位
      firstPosition: true
    };
  },
  methods: {
    handleTransitionContent(searchStr) {
      //獲取動態變化的搜尋詞
      if (searchStr !== "" && searchStr) {
        // 將特殊符號轉義
        let searchRegExp = searchStr.replace(/(\.|\+|\?|\*)/g, "\\$1");
        //若搜尋詞不為空,對搜尋詞進行替換 背景顏色變黃色
        return this.content
          .replace(
            new RegExp(searchRegExp, "g"),
            '<a style="background-color: yellow;"  >' + searchStr + "</a>"
          )
          .replace(/\n/g, "</br>");
      } else {
        return this.content.replace(/\n/g, "</br>");
      }
    },
    // 定位
    handlePosition(flag = "down") {
      // 容器
      const container = document.querySelector(".history-info-content");
      // 獲取所有a
      let alist = container.getElementsByTagName("a");
      let aListLength = alist.length;
      // 首次搜尋不執行定位的增減
      if (this.firstPosition) {
        flag = "";
      }
      switch (flag) {
        case "down": {
          //定位+1,走滿一圈歸0
          if (this.currentPosition < aListLength - 1) {
            this.currentPosition += 1;
          } else if (this.currentPosition == aListLength - 1) {
            this.currentPosition = 0;
          }
          break;
        }
        //定位-1,走滿一圈歸最後一位
        case "up": {
          if (this.currentPosition > 0) {
            this.currentPosition -= 1;
          } else if (this.currentPosition == 0) {
            this.currentPosition = aListLength - 1;
          }
          break;
        }
        default:
          break;
      }
      console.log("Bowen: change ", this.currentPosition);

      if (aListLength != 0) {
        // 當前的定位元素的背景顏色變紅
        for (const a of alist) {
          a.style.backgroundColor = "yellow";
        }
        let currentA = alist[this.currentPosition];
        console.log("Bowen: handlePosition -> currentA", currentA);
        currentA && (currentA.style.backgroundColor = "red");
        // 滾動到當前元素
        currentA.scrollIntoView({
          behavior: "smooth",
          block: "center",
          inline: "nearest"
        });
      }
      this.firstPosition = false;
    }
  },
  watch: {
    searchStr(searchStr) {
      // 輸入改變定位清零
      this.currentPosition = 0;
      // 賦值轉化後的字串
      this.transitionContent = this.handleTransitionContent(searchStr);
      // 設定為首次定位
      this.firstPosition = true;
    }
  },
  mounted() {
    // 首次先賦值
    this.transitionContent = this.handleTransitionContent("");
  }
};

元件使用的是vuetify ,主要可以看邏輯部分 element 等元件的用法大同小異