133 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			133 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /** | ||
|  |  * @fileoverview search 插件 | ||
|  |  */ | ||
|  | function Search (vm) { | ||
|  |   /** | ||
|  |    * @description 关键词搜索 | ||
|  |    * @param {regexp|string} key 要搜索的关键词 | ||
|  |    * @param {boolean} anchor 是否将搜索结果设置为锚点 | ||
|  |    * @param {string} style 搜索结果的样式 | ||
|  |    */ | ||
|  |   vm.search = function (key, anchor, style = 'background-color:yellow') { | ||
|  |     const res = [] | ||
|  |     const stack = []; | ||
|  | 
 | ||
|  |     // 遍历搜索
 | ||
|  |     (function traversal (nodes) { | ||
|  |       for (let i = 0; i < nodes.length; i++) { | ||
|  |         let node = nodes[i] | ||
|  |         if (node.type === 'text' && key) { | ||
|  |           const text = node.text | ||
|  |           const arr = text.split(key) | ||
|  |           if (arr.length > 1) { | ||
|  |             node = { | ||
|  |               name: 'span', | ||
|  |               attrs: {}, | ||
|  |               type: 'node', | ||
|  |               c: 1, | ||
|  |               s: 1, | ||
|  |               children: [] | ||
|  |             } | ||
|  |             vm.$set(nodes, i, node) | ||
|  |             for (let j = 0; j < arr.length; j++) { | ||
|  |               if (arr[j]) { | ||
|  |                 node.children.push({ | ||
|  |                   type: 'text', | ||
|  |                   text: arr[j] | ||
|  |                 }) | ||
|  |               } | ||
|  |               if (j !== arr.length - 1) { | ||
|  |                 // 关键词转为一个 span
 | ||
|  |                 node.children.push({ | ||
|  |                   name: 'span', | ||
|  |                   attrs: { | ||
|  |                     id: anchor ? 'search' + (res.length + 1) : undefined, // 用于锚点的 id
 | ||
|  |                     style: style | ||
|  |                   }, | ||
|  |                   // #ifdef VUE3
 | ||
|  |                   c: 1, | ||
|  |                   // #endif
 | ||
|  |                   children: [{ | ||
|  |                     type: 'text', | ||
|  |                     text: key instanceof RegExp ? key.exec(text)[0] : key | ||
|  |                   }] | ||
|  |                 }) | ||
|  |                 res.push(node.children[node.children.length - 1].attrs) | ||
|  |               } | ||
|  |             } | ||
|  |             if (key instanceof RegExp) { | ||
|  |               key.exec(text) | ||
|  |             } | ||
|  |             if (anchor) { | ||
|  |               for (let l = stack.length; l--;) { | ||
|  |                 if (stack[l].c) { | ||
|  |                   break | ||
|  |                 } else { | ||
|  |                   vm.$set(stack[l], 'c', 1) | ||
|  |                 } | ||
|  |               } | ||
|  |             } | ||
|  |           } | ||
|  |         } else if (node.s) { | ||
|  |           let text = '' | ||
|  |           // 复原上一次的结果
 | ||
|  |           for (let k = 0; k < node.children.length; k++) { | ||
|  |             const child = node.children[k] | ||
|  |             if (child.text) { | ||
|  |               text += child.text | ||
|  |             } else { | ||
|  |               text += child.children[0].text | ||
|  |             } | ||
|  |           } | ||
|  |           vm.$set(nodes, i, { | ||
|  |             type: 'text', | ||
|  |             text | ||
|  |           }) | ||
|  |           if (key && (key instanceof RegExp ? key.test(text) : text.includes(key))) { | ||
|  |             i-- | ||
|  |           } | ||
|  |         } else if (node.children) { | ||
|  |           stack.push(node) | ||
|  |           traversal(node.children) | ||
|  |           stack.pop() | ||
|  |         } | ||
|  |       } | ||
|  |     })(vm.nodes) | ||
|  | 
 | ||
|  |     return new Promise(function (resolve) { | ||
|  |       setTimeout(() => { | ||
|  |         resolve({ | ||
|  |           num: res.length, // 结果数量
 | ||
|  |           /** | ||
|  |            * @description 高亮某一个结果 | ||
|  |            * @param {number} i 第几个 | ||
|  |            * @param {string} hlstyle 高亮的样式 | ||
|  |            */ | ||
|  |           highlight (i, hlstyle = 'background-color:#FF9632') { | ||
|  |             if (i < 1 || i > res.length) return | ||
|  |             if (this.last) { | ||
|  |               res[this.last - 1].style = style | ||
|  |             } | ||
|  |             this.last = i | ||
|  |             res[i - 1].style = hlstyle | ||
|  |           }, | ||
|  |           /** | ||
|  |            * @description 跳转到搜索结果 | ||
|  |            * @param {number} i 第几个 | ||
|  |            * @param {number} offset 偏移量 | ||
|  |            */ | ||
|  |           jump: anchor | ||
|  |             ? (i, offset) => { | ||
|  |                 if (i > 0 && i <= res.length) { | ||
|  |                   vm.navigateTo('search' + i, offset) | ||
|  |                 } | ||
|  |               } | ||
|  |             : undefined | ||
|  |         }) | ||
|  |       }, 200) | ||
|  |     }) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = Search |