fuse.jsopen in new window

  • Bootstrap3:Typeahead.js或者magicsuggest.js
  • JQuery autocomplete和Select2

模糊匹配选项

includeMatches

  • 类型:boolean
  • 默认值:false 是否应该将匹配包含在结果集中。当为true时,结果集中的每条记录都将包含匹配字符的索引。因此,这些可以用于突出显示的目的。

minMatchCharLength

  • 类型:number
  • 默认值:1只有长度超过该值的匹配才会返回。(例如,如果您想忽略结果中的单个字符匹配,请将其设置为2)

location

  • 类型:数字
  • 默认值:0确定文本中期望找到的模式的大约位置。

threshold

  • 个人实验为 精确度
  • Type: number
  • Default: 0.6
  • 匹配算法在什么点放弃。阈值为0.0需要完全匹配(字母和位置),阈值为1.0可以匹配任何东西。
    • 字母和位置: 是否需要模糊匹配,
      • 0.5:中人 --》 中农过人 or 中国人民 都会匹配
      • 0.1:中人 --》 中人bai or 中人大学 精确到位置完全的精度

distance

  • 字符的长度 个人实验为 threshold * distance
  • Type: number
  • Default: 100
  • 确定匹配必须与模糊位置有多近(由 location 指定)。一个精确的字母匹配,即字符与模糊位置的距离,将得分为完全不匹配。0的距离要求匹配在指定的精确位置。1000的距离需要完美匹配,使用0.8的阈值在800个字符内找到位置。

ignoreLocation

  • Type: boolean
  • Default: false
  • 当为true时,搜索将忽略位置和距离,因此模式出现在字符串中的哪个位置并不重要。
  • 提示默认选项只搜索前60个字符。如果合理地预期匹配在这个范围内,这就足够了。要修改此行为,请设置适当的 location, threshold, distance (or ignoreLocation)

100 * 0.6 Determines how close the match must be to the fuzzy location (specified by location). An exact letter match which is distance characters away from the fuzzy location would score as a complete mismatch. A distance of 0 requires the match be at the exact location specified. A distance of 1000 would require a perfect match to be within 800 characters of the location to be found using a threshold of 0.8.

  • https://fusejs.io/api/options.html#threshold
  new Fuse(list, {
        shouldSort: true,   // 是否按分数对结果列表排序
        includeScore:true,  // 是否应将分数包含在结果集中。0分表示完全匹配,1分表示完全不匹配。
        threshold: 0.1,     // 匹配算法阈值。阈值为0.0需要完全匹配(字母和位置),阈值为1.0将匹配任何内容。
        location: 0,        // 确定文本中预期找到的模式的大致位置。
        distance: 100,
        maxPatternLength: 32,  // 模式的最大长度
        minMatchCharLength: 1,  // 模式的最小字符长度
        keys: [
          {
            name: "title",
            weight: 0.7,
          },
          {
            name: "path",
            weight: 0.3,
          },
        ],  // 搜索标题与路径
      });
 
    // 初始化
    init() {
      var options = {
        shouldSort: true, // 是否按分数对结果列表排序
        includeScore: true, //  是否应将分数包含在结果集中。0分表示完全匹配,1分表示完全不匹配。
        threshold: 0.6, // 匹配算法阈值。阈值为0.0需要完全匹配(字母和位置),阈值为1.0将匹配任何内容。
        /**
         * 确定匹配与模糊位置(由位置指定)的距离。
         *      一个精确的字母匹配,即距离模糊位置很远的字符将被视为完全不匹配。
         *  距离 (字符的长度) 为0要求匹配位于指定的准确位置, 
         *  距离 (字符的长度) 为1000则要求  
         *  完全匹配  位于使用阈值0.8 找到 的 位置的800个字符以内
         */
        location: 0, // 确定文本中预期找到的模式的大致位置。
        distance: 100,
        maxPatternLength: 32, // 模式的最大长度
        minMatchCharLength: 1, // 模式的最小字符长度
        // 搜索标题与作者名
        keys: ["title", "author.firstName"]
      };
      // 设置数据与参数
      this.fuse = new Fuse(this.books, options);
    }
  }
配置项描述默认值说明
isCaseSensitive大小写敏感FALSE
includeScore结果包含匹配度FALSE结果值:0表示完全匹配,1表示完全不匹配
includeMatches结果包含匹配字符的索引值FALSE可用于高亮显示搜索字符的场景
minMatchCharLength最小匹配长度1可用于需要至少几个字符才执行搜索的场景
shouldSort结果集排序TRUE结果集按照匹配度排序
findAllMatches查找所有项目FALSE即使找到了完全匹配项目也继续查找完其他所有项目
keys查找字段配置被查字段的路径(支持嵌套查找),权重(默认权重值为1),例如:[‘name.first’,{name:‘name.last’,weight:0.5}]
location匹配的字符预期的位置0匹配到的字符距离指定位置越近分数越高
threshold匹配度阈值0.60.0表示完全匹配(字符和位置);1.0将会匹配所有值
distancel匹配的字符在location指定位置的范围1000表示必须正好在location指定的位置
ignoreLocation忽略location配置参数FALSElocation和distance都会被忽略

实例

 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="../bootstrap/css/bootstrap.min.css">
    <script src="../assets/jquery.js"></script>
    <script src="../bootstrap/js/bootstrap.bundle.js"></script>

    <script src="../assets/vue.js"></script>

    <script src="../assets/search/fuse.js"></script>

    <style>
        .aa {
            background-color: #edeede;
        }


        .sear {
            height: 300px;
        }

        .st {
            background-color: rgb(113, 182, 171);
        }

        .dropdown-menu {
            position: relative;
            top: 0;
        }

        .pmu {
            display: flex;

            flex-direction: column;

        }

        .uili {
            /* border: 1px solid black; */
            margin: 3px;

        }

        .uili:hover {
            cursor: pointer;
            transform: scale(0.99);
            background-color: #ededed;
            border-radius: 3px;
        }

        .searchipt {
            background-color: rgb(140, 222, 216);

            outline: none;
            border: none;


        }
    </style>
</head>

<body>

    <div id="vapp" class="container-fluid aa">

        <div class="row">
            <div class="col-md-12 st"> </div>
        </div>

        <div class="row sear" style="background-color:#ededed ;">
            <div class="col-md-2 st"> </div>
            <div class="col-md-8">
                <input type="text" @focus="onFocus($event)" v-model:value="menuName"
                    class="form-control col-md-4 searchipt" placeholder="Username" aria-label="Username">

                <ul class="dropdown-menu pmu col-md-4">
                    <li class="uili" v-for="item in uls" @click='casUrl(item)' :key="item.id">
                        {{ item.name}}
                    </li>
                </ul>

            </div>
            <div class="col-md-2 st">22
            </div>
            <div>
            </div>
        </div>
    </div>
</body>


<script>
    new Vue({
        el: '#vapp',
        data() {
            return {
                msg: 'hello world',
                menuName: '',
                uls: [{
                        id: 1,
                        name: 'aaa'
                    },
                    {
                        id: 2,
                        name: 'bbb'
                    },
                    {
                        id: 3,
                        name: 'ccc'
                    }
                ]
            }
        },
        methods: {
            onFocus(e) {
                console.log(this)
                console.log((this.menuName))
                console.log(e)
            },
            casUrl(item) {
                const {
                    id,
                    name
                } = item
                console.log(id, name)
            }
        },
        watch: {
            'menuName'(newValue, oldValue) {
                console.log(oldValue, '<===原来 to 新===>', newValue)
                if (newValue == '') {
                    $('.dropdown-menu').hide()
                } else {
                    const list = [{
                            "title": "申天暗室逢灯",
                            "author": {
                                "firstName": "John",
                                "lastName": "Scalzi"
                            }
                        }, {
                            "title": "提哈德发大发天",
                            "author": {
                                "firstName": "John",
                                "lastName": "Scalzi"
                            }
                        }, {
                            "title": "三个月后单位",
                            "author": {
                                "firstName": "John",
                                "lastName": "Scalzi"
                            }
                        }, {
                            "title": "他说的感动",
                            "author": {
                                "firstName": "John",
                                "lastName": "Scalzi"
                            }
                        },
                        {
                            "title": "赵agag大幅度发给的天",
                            "author": {
                                "firstName": "Steve",
                                "lastName": "Hamilton"
                            }
                        },
                        {
                            "title": "申庄人",
                            "author": {
                                "firstName": "Remy",
                                "lastName": "Sharp"
                            }
                        },
                        {
                            "title": "李白白",
                            "author": {
                                "firstName": "P.D",
                                "lastName": "Woodhouse"
                            }
                        },
                        {
                            "title": "白天和黑夜",
                            "author": {
                                "firstName": "P.D",
                                "lastName": "Woodhouse"
                            }
                        },
                        {
                            "title": "韩申",
                            "author": {
                                "firstName": "P.D",
                                "lastName": "Woodhouse"
                            }
                        }
                    ]
                    const fuse = new Fuse(list, {
                        // isCaseSensitive: false,
                        // includeScore: false,
                        shouldSort: true,
                        // includeMatches: false,
                        // findAllMatches: false,
                        // minMatchCharLength: 1,
                        // location: 0,
                        threshold: 0.3,
                        // distance: 100,
                        // useExtendedSearch: false,
                        // ignoreLocation: false,
                        // ignoreFieldNorm: false,
                        // fieldNormWeight: 1,
                        keys: [{
                            name: "title",
                            weight: 0.5,
                        }, ]
                    });
                    console.log('search    /// / ', fuse.search(newValue))

                    let rls = fuse.search(newValue)
                    let varr = []
                    for (let {
                            item,
                            refIndex
                        } of rls) {
                        console.log(item.title)
                        varr.push({
                            id: refIndex,
                            name: item.title
                        })
                    }
                    this.uls = varr
                    $('.dropdown-menu').show()
                }
            }
        },

        mounted() {
            $('.dropdown-menu').show()
            console.log('init app')
        }
    })
</script>

</html>

输入框自动补全

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Autocomplete - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
  <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
  <script>
    $(function () {
      var availableTags = [
        "ActionScript",
        "AppleScript",
        "Asp",
        "BASIC",
        "C",
        "C++",
        "Clojure",
        "COBOL",
        "ColdFusion",
        "Erlang",
        "Fortran",
        "Groovy",
        "Haskell",
        "Java",
        "JavaScript",
        "Lisp",
        "Perl",
        "PHP",
        "Python",
        "Ruby",
        "Scala",
        "Scheme"
      ];
      $("#tags").autocomplete({
        source: availableTags
      });
    });
  </script>
</head>

<body>

  <div class="ui-widget">
    <label for="tags">Tags: </label>
    <input id="tags">
  </div>


</body>

</html>