用Lucene建立搜索索引

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。

在本课程中,您将了解Lucene。 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式。 此外,您将学习如何将Lucene Search集成到您自己的应用程序中,以提供强大的搜索功能。 在这里查看 !

目录

1.简介 2.了解索引操作
2.1倒排索引 2.2字段类型 2.3细分 2.4文件编号 2.5搜索索引
3.创建索引 4.基本索引操作
4.1核心索引类 4.2将数据添加到索引
5.文件和领域
5.1文件 5.2领域 5.3在Lucene中增强文档

1.简介

该索引是利用Lucene的任何组件的核心。 就像书籍的索引一样,它组织所有数据,以便可以快速访问。 索引由包含一个或多个字段的文档组成。 文档和字段可以代表我们选择的任何内容,但一个常见的隐喻是:文档表示数据库表中的条目,而字段类似于表中的字段。

2.了解索引操作

让我们看一下Lucene搜索索引的图形表示。

图1

图1

简而言之,当Lucene对文档进行索引时,它会将其分解为许多术语。 然后,它将术语存储在索引文件中,其中每个术语与包含该术语的文档相关联。 我们可以把它当作一个哈希表。 术语是使用分析器生成的,该分析器将每个单词的词根都提取出来。 发出查询时,将通过用于构建索引的同一分析器来处理该查询,然后使用该分析器在索引中查找匹配项。 这提供了与查询匹配的文档列表。

现在,让我们看一下整个Lucene搜索过程。

基本概念是索引,文档,字段和术语。

  1. 索引包含文档的集合。
  2. 文档是字段的集合。
  3. 字段是术语的集合。
  4. 术语是成对的字符串<field,term-string>。

2.1倒排索引

索引存储有关术语的统计信息,以使基于术语的搜索更加高效。 Lucene的索引属于称为反向索引的索引族。 这是因为它可以长期列出包含它的文档。 这与文档中列出术语的自然关系相反。

2.2字段类型

在Lucene中,可以存储字段,在这种情况下,它们的文本将以非反转的方式按字面意义存储在索引中。 反转的字段称为索引。 字段可以被存储和被索引。

可以将字段的文本标记为要索引的术语,或者可以将字段的文本从字面上用作要索引的术语。 大多数字段都是标记化的,但有时对于某些标识符字段按字面意义进行索引很有用。

2.3细分

Lucene索引可以由多个子索引或段组成。 每个段都是完全独立的索引,可以分别进行搜索。 索引按以下方式演变:

  1. 为新添加的文档创建新的细分。
  2. 合并现有的细分。
  3. 搜索可能涉及多个段和/或多个索引,每个索引可能由一组段组成。

2.4文件编号

在内部,Lucene通过整数文档号引用文档。 添加到索引的第一个文档编号为零,并且随后添加的每个文档的编号都比前一个大。

请注意,文档编号可能会更改,因此在将这些编号存储在Lucene之外时应格外小心。 特别是,在以下情况下数字可能会更改:

存储在每个段中的数字仅在该段内是唯一的,并且必须进行转换才能在更大的上下文中使用它们。 标准技术是根据该段中使用的数字范围为每个段分配一个值范围。 要将文档编号从段转换为外部值,需要添加段的基本文档编号。 要将外部值转换回特定于细分的值,可以通过外部值所在的范围来标识细分,然后减去细分的基值。 例如,可以合并两个五个文档的段,以便第一个段的基值为零,第二个为五个。 第二段的文档三的外部值为8。

删除文档后,在编号中会留出空白。 随着索引通过合并的发展,这些最终被删除。 合并段时删除已删除的文档。 因此,新合并的段在编号上没有间隙。

2.5搜索索引

搜索索引由javascript函数定义。 它以类似于视图的地图功能的方式运行在所有文档上,并定义了搜索可查询的字段。 搜索索引是数据库的一种变体。 它与RDBMS相似,因为它需要快速查找密钥,但是大部分数据驻留在辅助存储上。

3.创建索引

到目前为止,我们已经看到了Lucene索引的所有组成部分。 在本节中,我们将使用Lucene索引创建文档索引。

考虑一个项目,学生在其中提交年度杂志文章。 输入控制台包含学生姓名,文章标题,文章类别和文章正文的选项。 我们假设该项目正在网络上运行并且可以通过它进行访问。 要为这篇文章建立索引,我们需要文章本身,作者的姓名,撰写日期,文章的主题,文章的标题以及文件所在的URL。 利用这些信息,我们可以构建一个程序,该程序可以正确索引文章以使其易于查找。

让我们看一下我们类的基本框架,包括我们将需要的所有导入。

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits; import java.util.Date; public class ArticleIndexer { }

我们需要添加的第一件事是将文章转换为Document对象的方法。

为此,我们将使用方法createDocument()

private Document createDocument(String article, String author,String title, String topic,String url, Date dateWritten) { Document document = new Document();document.add(Field.Text("author", author));document.add(Field.Text("title", title));document.add(Field.Text("topic", topic));document.add(Field.UnIndexed("url", url));document.add(Field.Keyword("date", dateWritten));document.add(Field.UnStored("article", article));return document;}

首先,我们创建一个新的Document对象。 接下来要做的是将文章的不同部分添加到Document 。 我们为每个部分提供的名称完全是任意的,并且像HashMap键一样工作。 使用的名称必须是String 。 Document的add方法将采用一个Field对象,该对象是使用Field类提供的静态方法之一构建的。 提供了四种将Field对象添加到Document的方法。

Field.Keyword –数据已存储并建立索引,但未标记化。 这对于应保留不变的数据(例如日期)最有用。 实际上,Field.Keyword可以将Date对象作为输入。

Field.Text –数据被存储,索引和标记化。 Field.Text字段不应用于诸如文章本身之类的大量数据,因为索引将变得非常大,因为它将包含文章的完整副本以及标记化的版本。

Field.UnStored –不存储数据,但对其进行索引和标记化。 大量数据(例如文章的文本)应放置在未存储的索引中。

Field.UnIndexed –数据已存储但未建立索引或标记化。 它与要与搜索结果一起返回的数据一起使用,但实际上不会在该数据上进行搜索。 在我们的示例中,由于我们不允许搜索URL,因此没有理由对其进行索引,但是我们希望在找到搜索结果后将其返回给我们。

现在我们有了一个Document对象,我们需要获得一个IndexWriter来将此Document写入索引。

String indexDirectory = "lucene-index"; private void indexDocument(Document document) throws Exception {Analyzer analyzer  = new StandardAnalyzer();IndexWriter writer = new IndexWriter(indexDirectory, analyzer, false);writer.addDocument(document);writer.optimize();writer.close();}

我们首先创建StandardAnalyzer ,然后使用分析器创建IndexWriter 。 在构造函数中,我们必须指定索引将驻留的目录。 构造函数末尾的布尔值告诉IndexWriter是创建新索引还是添加到现有索引。 在将新文档添加到现有索引时,我们将指定false。 然后,我们将Document添加到索引。 最后,我们优化然后关闭索引。 如果要添加多个Document对象,则应始终进行优化,然后在将所有Document对象都添加到索引之后关闭索引。

现在,我们只需要添加一种将各个部分组合在一起的方法即可。

为了驱动索引​​操作,我们将编写一个indexArticle()一些参数的方法indexArticle()

public void indexArticle(String article, String author,String title, String topic,String url, Date dateWritten)throws Exception {Document document = createDocument(article, author,title, topic,url, dateWritten);indexDocument(document);}

对文章运行该文章会将其添加到索引中。 将IndexWriter构造函数中的布尔值更改为true会创建一个索引,因此我们应该在第一次创建索引时以及每次要从头开始重建索引时使用它。 现在我们已经构建了索引,我们需要在索引中搜索文章。

索引存储为单个目录中的一组文件。

索引由任意数量的独立段组成,这些段存储有关已索引文档子集的信息。 每个段都有自己的术语词典,术语词典索引和文档存储(存储的字段值)。 所有段数据都存储在_xxxxx.cfs文件中,其中xxxxx是段名称。

创建索引段文件后,将无法对其进行更新。 新文档将添加到新段中。 删除的文档仅在可选的.del文件中标记为已删除。

4.基本索引操作

索引数据

Lucene让我们可以索引文本格式的任何可用数据。 Lucene几乎可以用于任何数据源,只要可以从中提取文本信息即可。 我们可以使用Lucene对存​​储在HTML文档,Microsoft Word文档,PDF文件等中的数据进行索引和搜索。 索引数据的第一步是使其以简单文本格式可用。 可以使用自定义解析器和数据转换器。

索引过程

索引编制是将文本数据转换为便于快速搜索的格式的过程。 一个简单的类比是您在书末找到的索引:该索引将您指向书中出现的主题的位置。

Lucene将输入数据存储在称为反向索引的数据结构中,该数据结构作为一组索引文件存储在文件系统或内存中。 大多数Web搜索引擎使用反向索引。 它使用户可以执行快速的关键字查找,并找到与给定查询匹配的文档。 在将文本数据添加到索引之前,它需要由分析器处理(使用分析过程)。

分析

分析将文本数据转换为基本的搜索单位,称为术语。 在分析过程中,文本数据会经历多种操作:提取单词,删除常用单词,忽略标点符号,将单词简化为词根形式,将单词更改为小写字母等。分析仅在建立索引和查询解析之前进行。 分析将文本数据转换为标记,并将这些标记作为术语添加到Lucene索引中。

Lucene带有各种内置分析器,例如SimpleAnalyzerStandardAnalyzerStopAnalyzerSnowballAnalyzer等。 它们在标记文本和应用过滤器的方式上有所不同。 由于分析会在索引编制之前删除单词,因此会减小索引大小,但会对查询处理的精度产生负面影响。 通过使用Lucene提供的基本构建块创建自定义分析器,可以对分析过程进行更多控制。 表1显示了一些内置分析仪及其处理数据的方式。

4.1核心索引类

目录

代表索引文件存储位置的抽象类。 通常主要使用两个子类:

FSDirectory —目录的实现,在实际的文件系统中存储索引。 这对于大索引很有用。

RAMDirectory —将所有索引存储在内存中的实现。 这适用于较小的索引,这些索引可以完全加载到内存中,并在应用程序终止时销毁。 由于索引保存在内存中,因此速度相对较快。

分析仪

如所讨论的,分析器负责预处理文本数据并将其转换为存储在索引中的令牌。 IndexWriter接受用于对数据建立索引之前对其进行标记化的分析器。 为了正确地为文本建立索引,您应该使用适合需要被索引的文本语言的分析器。

默认分析器适用于英语。 Lucene沙箱中还有其他一些分析器,包括中文,日文和韩文的分析器。

IndexDeletionPolicy

用于实现自定义从索引目录中删除过时提交的策略的接口。 默认的删除策略是KeepOnlyLastCommitDeletionPolicy ,它仅保留最新的提交,并在完成新提交后立即删除所有先前的提交。

索引作家

创建或维护索引的类。 它的构造函数接受一个布尔值,该布尔值确定是创建新索引还是打开现有索引。 它提供了添加,删除或更新索引中文档的方法。

对索引所做的更改最初会在内存中进行缓冲,并定期刷新到索引目录。 IndexWriter公开了几个字段,这些字段控制索引在内存中的缓冲方式以及如何将其写入磁盘。 除非调用IndexWriter的commit或close方法,否则对IndexReader不到对索引所做的更改。 IndexWriter为目录创建一个锁定文件,以防止索引同时更新导致索引损坏。 IndexWriter允许用户指定可选的索引删除策略。

4.2将数据添加到索引

将文本数据添加到索引涉及两个类。

字段表示在搜索中查询或检索的一条数据。 Field类封装一个字段名称及其值。 Lucene提供了一些选项来指定是否需要对字段进行索引或分析以及是否需要存储其值。 在创建字段实例时可以传递这些选项。 下表显示了字段元数据选项的详细信息。

选项 描述
Field.Store.Yes 用于存储字段的值。 适用于显示搜索结果的字段,例如文件路径和URL。
Field.Store.No 字段值未存储-例如,电子邮件正文。
Field.Index.No 适用于未搜索的字段-通常与存储的字段(例如文件路径)一起使用。
Field.Index.ANALYZED 用于索引但未分析的字段。 它完整​​地保留了字段的原始值,例如日期和个人名称。
Field.Index.NOT_ANALYZED 用于索引但未分析的字段。 它完整​​地保留了字段的原始值,例如日期和个人名称。

字段元数据选项的详细信息

而文档是字段的集合。 Lucene还支持增强文档和字段,如果要重视某些索引数据,这是一个有用的功能。 为文本文件建立索引包括将文本数据包装在字段中,创建文档,使用字段填充文本,以及使用IndexWriter将文档添加到索引中。

5.文件和领域

如您先前所见,文档是索引和搜索过程的单元。

5.1文件

文档是一组字段。 每个字段都有一个名称和一个文本值。 字段可以与文档一起存储,在这种情况下,它会随文档的搜索命中一起返回。 因此,每个文档通常应包含一个或多个唯一标识它的存储字段。

您将文档添加到索引,并且在执行搜索之后,您将获得结果列表,它们是文档。 文档只是字段的非结构化集合。

5.2领域

字段是Lucene.net的实际内容所有者:它们基本上是一个哈希表,具有名称和值。 如果我们拥有无限的磁盘空间和无限的处理能力,那就是我们所需要知道的。 但是不幸的是,磁盘空间和处理能力受到限制,因此您不能仅分析所有内容并将其存储到索引中。 但是Lucene.net提供了将字段添加到索引的不同方法。

Lucene提供了四种不同类型的字段供开发人员选择: KeywordUnIndexedUnStoredText 。 您应该使用哪种字段类型取决于您要如何使用该字段及其值。

关键字字段未标记,但被逐字索引并存储在索引中。 此字段适用于原始值应完整保留的字段,例如URL,日期,个人姓名,社会保险号,电话号码等。

未索引字段既没有标记也没有索引,但它们的值存储在逐字索引中。 该字段适用于需要与搜索结果一起显示但绝不会直接搜索其值的字段。 由于未对这种类型的字段建立索引,因此对其进行搜索很慢。 由于此类型的字段的原始值存储在索引中,因此如果存在索引大小的问题,则此类型不适合存储具有非常大值的字段。

未存储字段与未索引字段相反。 此类型的字段已标记并建立索引,但未存储在索引中。 此字段适用于索引大量不需要以其原始形式检索的文本,例如网页正文或任何其他类型的文本文档。

文本字段被标记,索引并存储在索引中。 这意味着可以搜索此类型的字段,但请注意存储为“文本”字段的字段的大小。

如果您回顾一下LuceneIndexExample类,您将看到我使用了Text字段:

document.add(Field.Text("fieldname", text));

如果要更改字段fieldname的类型,我们将调用Field类的其他方法之一:

document.add(Field.Keyword("fieldname", text));

要么

document.add(Field.UnIndexed("fieldname", text));

要么

document.add(Field.UnStored("fieldname", text));

尽管Field.TextField.KeywordField.UnIndexedField.UnStored调用最初看起来像是对构造函数的调用,但它们实际上只是对不同Field类方法的调用。 表1总结了不同的字段类型。

现场方法/类型 代币化 索引 已储存
Field.Keyword(String, String) 没有
Field.UnIndexed(String, String) 没有 没有
Field.UnStored(String, String) 没有
Field.Text(String, String)
Field.Text(String, Reader) 没有

表1:不同字段类型的概述。

5.3在Lucene中增强文档

在“信息检索”中,文档与搜索的相关性通过与查询的相似程度来衡量。 Lucene中实现了几种相似性模型,您可以通过扩展相似性类并使用Lucene保存的索引统计信息来实现自己的相似性模型。 还可以为文档分配静态分数,以表示它们在整个语料库中的重要性,而与正在执行的查询无关,例如其受欢迎程度,评分或PageRank。

在Lucene 4.0之前,您可以通过调用document.setBoost为文档分配静态分数。 在内部,通过将字段的提升因子乘以文档的提升因子,将提升应用于文档的每个字段。 但是,这永远无法正常工作,并且取决于所执行查询的类型,可能根本不会影响文档的排名。

通过在Lucene中添加DocValues,增强文档就像添加NumericDocValuesField并将其用于CustomScoreQuery一样简单, CustomScoreQuery将计算所得的分数乘以“ boost”字段的值。 下面的代码示例说明了如何实现此目的:

// add two documents to the index
Document doc = new Document();
doc.add(new TextField("f", "test document", Store.NO));
doc.add(new NumericDocValuesField("boost", 1L));
writer.addDocument(doc); doc = new Document();
doc.add(new TextField("f", "test document", Store.NO));
doc.add(new NumericDocValuesField("boost", 2L));
writer.addDocument(doc); // search for 'test' while boosting by field 'boost'
Query baseQuery = new TermQuery(new Term("f", "test"));
Query boostQuery = new FunctionQuery(new LongFieldSource("boost"));
Query q = new CustomScoreQuery(baseQuery, boostQuery);
searcher.search(q, 10);

通过编写一个简单的公式,新的Expressions模块也可以用于增强文档,如下所示。 尽管它比使用CustomScoreQuery更为冗长,但它通过计算更复杂的公式(例如sqrt(_score)+ ln(boost))变得微不足道。

Expression expr = JavascriptCompiler.compile("_score * boost");
SimpleBindings bindings = new SimpleBindings();
bindings.add(new SortField("_score", SortField.Type.SCORE));
bindings.add(new SortField("boost", SortField.Type.LONG));
Sort sort = new Sort(expr.getSortField(bindings, true));
searcher.search(baseQuery, null, 10, sort);

既然Lucene允许在不重新索引文档的情况下更新NumericDocValuesField ,那么您可以将频繁更改的字段(受欢迎程度,评分,价格,最后修改时间…)并入提升因子中,而无需每次对其中任何一个更改时都重新索引文档。

翻译自: https://www.javacodegeeks.com/2015/09/building-a-search-index-with-lucene.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

twitter api_Java应用程序上的Twitter API

twitter api是否曾想过将推文附加到Java应用程序&#xff1f; 我为此寻找了最好的API&#xff0c;很幸运&#xff0c;我找到了它&#xff01; http://twitter4j.org/ 一个简单的方法&#xff1a; 我们需要做的第一件事是在您的Twitter帐户中创建一个应用程序&#xff0c;为其授…

垂直和水平装饰

装饰器模式是在不更改其接口的情况下向对象添加功能的最佳方法之一。 我经常使用可组合装饰器&#xff0c;并且总是会问自己在功能列表必须可配置时如何正确设计它们。 我不确定我的答案是否正确&#xff0c;但是这里有一些值得深思的地方。 公寓&#xff08;1960&#xff09;…

cygwin配置git

对于windows用户来说&#xff0c;使用git bash经常会出现乱码情况&#xff0c;那么一款优质高尚的软件&#xff0c;值得推荐一下了&#xff0c;那就是cygwin 下载cygwin后&#xff0c;在安装过程中&#xff0c;安装git&#xff0c;安装vim编辑器 然后会在安装目录下看到类linux…

前端代码规范网址导航(总结)

在大公司代码规范是非常重要的一件事情,多人协作,还有代码评审。所以能写出漂亮的代码非常重要。 这就好比你自己在家,无论是穿大裤衩子,还是背心,甚至是光膀子,都没人管你。但你要出门去约会,就要把最好的一面展现给别人。这是对别人的尊重,也是给自己的背书。所以遵…

JLupin Next Server乍一看

JEE基础结构现在有了一个新的管理解决方案– JLupin Next Server。 它为应用程序实现提供了另一种方法。 它提供什么&#xff1f; 用于实现JEE应用程序的现有解决方案受到限制。 通过新的应用程序管理方式&#xff0c;JLupin Next Server打破了所有障碍。 JEE的足迹 良好实践…

读《第一次把事情做对》有感

上班的时候&#xff0c;领导在群里发了一个PDF书籍《第一次把事情做对》&#xff0c;被这个书籍名称吸引住了&#xff0c;因为作为程序员每天有开发新任务&#xff0c;解决旧任务的BUG&#xff0c;第一次就把事情做的完全正确几乎不可能呀&#xff0c;觉得很有看的必要&#xf…

做了三年前端,你才知道10分钟就能实现一个PC版魔方游戏

导读&#xff1a;最近手头有点紧&#xff0c;看到很多小朋友都在玩魔方&#xff0c;又没有money买&#xff0c;只能自己用JavaScriptcss实现一个&#xff0c;在电脑端就能开启魔方之旅。 目录 项目启动演示 项目目录 ​源码地址 项目启动演示 前端使用JavaScript和纯CSS实现…

15K的前端应届毕业生,就因为掌握了这些知识点!(前端企业级开发必备)

目录 1.前端开发 下载安装VScode 优化配置 2、插件安装 3、设置字体大小 4、开启完整的Emmet语法支持 5、视图 2.Node.js 入门 2.1、什么是Node.js 2.2、Node.js有什么用 2.3、安装 下载&#xff1a; 2.4、快速入门 2.5、服务器端应用开发 3、ES6入门 3.2、let声…

[Training Video - 1] [Selenium Basics] [Download and Install Selenium]

Download Selenium Jars Configure jars in eclipse Webdriver http://docs.seleniumhq.org/download/ Selenium RC http://code.google.com/p/selenium/downloads/detail?nameselenium-remote-control-1.0.3.zip&can2&q转载于:https://www.cnblogs.com/MasterMonkInT…

【0元试用微软 Azure人工智能认知服务】这个人脸识别功能太强大啦

导读&#xff1a;这个由美丽的客服小姐姐提前申请好了企业试用的账号&#xff0c;个人的话还得需要visa卡。 官网地址&#xff1a;azure.cn 登录地址&#xff1a;portal.azure.cn 目录 1.简介 2.Azure 认知服务是什么&#xff1f; ​ 3.认知服务的四种职能 4.人脸API 5.新建一…

OpenMap教程3 –使用MapHandler构建基本的地图应用程序–第2部分

1.简介 在上一教程中&#xff0c;我们看到了MapHandler如何将各种组件连接在一起&#xff08;更具体地说&#xff0c;是从MapHandlerChild派生的类&#xff09;。 我们看到了如何以编程方式执行此操作&#xff0c;但是还有另一种声明性地使用openmap.properties 。 样本OpenMa…

《javaScript100例|01》超级经典一套鼠标控制左右滚动图片带自动翻滚

目录 HTML示例 图片示例 HTML示例 <html > <head> <meta http-equiv"Content-Type" content"text/html; charsetgb2312" /> <title>超级经典一套鼠标控制左右滚动图片带自动翻滚</title> <style type"text/css&quo…

[BZOJ1007] [HNOI2008] 水平可见直线 (凸包)

Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的. 例如,对于直线:L1:yx; L2:y-x; L3:y0 则L1和L2是可见的,L3是被覆盖的. 给出n条直线,表示成yAxB的形式(|A|,|B|<500000),且n条直线两…

《javaScript100例|02》超级经典一套鼠标控制左右滚动图片带自动翻滚

目录 效果图 JS示例 源码地址&#xff1a; 效果图 JS示例 <title>JavaScript切换图片</title> <script> function showDaTu(src){ document.getElementById("defaultImg").srcsrc; } </script> <img src"wall1.jpg" id"…

抽象工厂设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

《javaScript100例|03》自写javaScript+CSS轮显效果

目录 效果图 代码示例 源码地址&#xff1a;自写JsCSS轮显效果.rar-互联网文档类资源-CSDN下载https://download.csdn.net/download/weixin_41937552/37380520 效果图 代码示例 <html xmlns"http://www.w3.org/1999/xhtml"> <head> <meta http-equ…

《javaScript100例|04》自动播放——Js幻灯片缓冲效果

目录 效果图 示例 源码地址&#xff1a; 效果图 示例 <html> <head> <title>自动播放——幻灯片缓冲效果</title> <style> body,div,ul,li{margin:0;padding:0;} ul{list-style-type:none;} body{background:#000;text-align:center;font:12p…

PHP+jquery 树状菜单

本项目开发过程中涉及树状菜单&#xff0c;于是做如下分享菜单实现 不足之处请大牛指点并见谅&#xff08;如图&#xff09; 1&#xff1a;数据表涉及字段 id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 系统菜单ID, pid int(10) DEFAULT NULL COMMENT 父级ID, name va…

vue计算属性computed与监听属性watch的基本使用

目录 Vue.js 计算属性 Vue.js 监听属性 Vue.js 计算属性 计算属性关键词: computed。 计算属性在处理一些复杂逻辑时是很有用的。 反转字符串的示例 <!DOCTYPE html> <html> <he

vue样式绑定与事件处理器的基本使用

目录 Vue.js 样式绑定 Vue.js 事件处理器 事件修饰符 Vue.js 样式绑定