Alan Hou的个人博客

电商系统Shopify二次开发02:Liquid基础学习

本文我们学习Liquid的基础知识,主要包含如下内容:

学习完本文,读者将会对Liquid的逻辑有更深的了解,也能 GET 到操作各种类型数据的运算符以及Liquid删除烦人的空白字符的方法等知识。通过学习如何使用逻辑运算符以及操作句柄属性,我们能学到生成各类动态特性的知识,有助于未来编写高质量的复杂代码。

Liquid是什么?

上一篇文章中,我们对Shopify有了一定的了解。学习了Shopify是什么,如何创建Shopify伙伴账号以及如何管理主题。最后,我们还探讨了一下主题的文件结构及其所包含的目录,基础文件放在Layout目录中,读者可能也注意到了其中大部分文件的后缀名都是.liquid。那么 Liquid 究竟是什么样的存在呢?

Liquid是一个由Shopify联合创始人及CEO Tobias Lütke所创建的开源项目。Liquid作为一种模板语言,它变量连接着Shopify店铺的数据与主题中的HTML内容,让我们可以将静态模板页面变成动态、强大、效果很好的电商网站。可以把Liquid元素看成占位符,在文件内代码译、发往浏览器时会填充相应的数据。

自2006年起,Liquid不断地成长、演化。时至今日,有多个web应用依赖于Liquid,Shopify是其中之一,表明对Liquid的需求在不断增长。学习Liquid是技术得以精进很好途径,其语法易学,很快我们就能掌握Liquid并使用它创建复杂的功能。

学习Liquid及其定界符

分辨Liquid有两种方式,一种是通过其文件后缀名.liquid。作为一种模板语言,Liquid文件是静态动态内容的结合体。

虽然浏览器可以很快速地处理HTML代码,但并不能处理、解析Liquid代码。可以把Shopify URL提交到浏览器拆解成5个逻辑步骤:

  1. Shopify服务端判断你所要访问的是哪一个店铺。
  2. 根据我们当前请求信息的页面类型,Shopify尝试从在线主题目录中定位、选取相应的Liquid模板。
  3. 在成功确定所请求的Liquid模板后,Shopify服务端开始将占位符替换为平台存储的实际数据。
  4. 在Shopify完成占位符并执行所选取模板中的逻辑后,浏览器会接收到所编译的HTML文件。
  5. 现在浏览器接收到了响应的HTML文件,会开始处理该文件并加载所需的资源,包括JavaScript、样式表和图片等。

另一种辨别Liquid文件和代码的方式是其两个定界符:

上例中,我们可以使用{{ collection.title }}的结果来获取集合的名称。那如果想要显示集合的描述,而出于某种原因,collection description并未返回任何内容呢?我们会得到一段不完整的信息:

Our collection description is

为确保这一情况不会发生,我们需要使用Liquid逻辑运算符和比较运算符结合一些Shopify的数据类型来检查该数据值是否存在。

学习比较运算符

通过Liquid,我们可以访问7种比较运算符,可以组合起来创建代码所需的某种逻辑流。下面来逐步了解:

使用逻辑运算符

除比较运算符外,我们还可以使用两个逻辑运算符,用于组合多个条件来形成复杂语句。可以分成以下两组:

我们已经学习到了很多有关逻辑运算符和比较运算符的知识。但是只学了两个值进行比较。那如果检测某个值,比如集合描述是否存在呢?因为我们不知道collection.description会返回什么内容,就无法以现有的知识执行检测。要完成这一任务,首先我们要学习Liquid中能够使用的各种数据类型。

数据类型

至此我们讲到了两种数据类型,也即字符串和数值类型。但在Liquid中,有6种不同的数据类型:

Strings

字符串是用于表示文件的一种数据类型。因为字符串可能包含字母、数字或特殊字符,所以应当使用双引号进行包裹:

上例中,我们查看产品标题中是否含有字符串“Book”“2021”,如果包含,则显示消息。

Number

数值类型无需使用引号,使用它来表示如下两种类型的数值数据:

上例中,我们检测产品价格是否大于25,同时又小于3500。如果两个条件都为真,则显示消息。记住这里使用的是and运算符,所以两个条件必须都为真,如果其中之一为假,就不会显示消息。

注意用于比较的两个数字,25 或 3500,都没有使用引号。否则就会变成字符串,那就会像之前那样无法和product.price所返回的值进行比较。

Boolean

布尔是一种值为truefalse的数据类型:

从例子中可以看出,类似数值类型,布尔值不使用引号。如果客户订阅了邮件,customer.accepts_marketing对象就会为真,消息也会显示。

Nil

Nil是一种代码无返回结果,返回空值的数据类型。因为nil不返回任何值,我们可以用它来检测语句是否为真。但应当注意我们只能使用nil来检测值是否存在。不能使用nil来检测值的内容:

上例中,我们使用条件语句查询访问店铺的客户是否注册了账户。注意并没有在customer对象后添加任何运算符或数据类型。其原因是nil是一种特殊的空值。它不是一个内容为nil的字符串或一个变量,并不需要任何视觉上的表现。

我们可以将Liquid中的值分成两类:

因为nil被看成是假,用户没有注册店铺账号的话就不会显示消息。有注册条件语句就返回true,消息正常显示。

虽然nil用户很大,但并不是万能的。读者如果记得的话,前面我们使用collection.description 来查看集合的描述内容。

如果集合描述中定义了内容,消息就会正确显示。但如果没有定义集合描述,那么collection.description会返回空,并且我们会得到一条不完整的消息:

我们说过仅能使用nil来检测某一元素如对象是否存在。它无法检测其中的内容,什么意思呢?

本例中,我们把元素封装在条件语句中,使用nil数据类型来检测collection.description实例是否存在。但可以看到这不是我们所希望的结果:

因为nil只检测元素是否存在,本例中条件语句发现collection.description虽然为空,但却是存在的。还记得Liquid中除了false和nil默认都为真吗?也就是说即使是空字符串,也被看成是真。出于这一原因,虽然我们的collection.descriptio实例为空且返回空字符串,其结果为真。因此条件语句所包含的代码会显示出来。

要解决这一问题,我们不检测其值是事存在,而是检测值是否为空:

在本例中,我们对blank使用了等号参数来检测集合描述是否为空。如果条件语句的结果是collection.description不为空,所定义的消息就会显示。否则,条件语句会返回false,其中的消息就不会显示。

Array

数组是一种包含元素列表的数据结构,通常元素类型相同。注意我们不能仅使用Liquid初始化数组,但可以将字符串分解成子字符串数组,可通过如下两种方式访问数据:

虽然对数组使用循环快速输出比单独调用数组中的每一项更为容易,但应该了解这两种方法,有助于在稍后实现复杂功能。

EmptyDrop

最后一种数据类型是EmptyDrop,在访问此前已删除对象或句柄进行禁用时会得到这一结果。

在学习最后这个数据类型之前,我们需要先学习什么是句柄,如果如何找到它。

查找句柄

句柄是小写的页面标题,使用中间杠()来替换特殊字符及空格。类似在数组中使用位置索引来访问子项内容,我们可以使用页面句柄来访问Liquid对象的属性。

现在知道了什么是页面句柄,我们试着在店铺中创建一个页面将其放入上下文,实操下刚刚学习的知识:

  1. 新建页面首先我们需要通过https://my-store-name.myshopify.com/admin访问店铺,然后使用注册的Shopify伙伴账号登录。也可以直接访问Shopify伙伴网站https://www.shopify.com/partners,使用上一篇文章所注册的账号进行登录,再点击左侧边栏的Store按钮,接着点击店铺名旁的Log in按钮。
  2. 成功登录店铺后,点击左侧边栏Sales channels之下的Online Store展开其中的菜单,然后点击Pages,就会进入到店铺的Pages页面:
  3. 进入后,因为这是一个新店铺,还没有内容,仅能看到一个Add page按钮。否则我们会看到店铺中可以访问的所有页面。点击Add page按钮创建第一个页面。
  4. 在进入新建页面的流程后,会进入一个页面,其中可定义新页面的名称、描述、可见性等内容并进行模板的选择。本例中我们仅需输入标题,在Visibility中选择VisibleContent字段当前可以留空。标题我们输入Learning about the page handle,确保选择了Visible,然后就可以点击Save按钮了:
  5. 创建好页面后,我们可以点击页面下方的Edit website SEO按钮查看页面句柄,它会展开、显示该页面的SEO信息,可以看到如下编辑信息:

前面说到句柄是小写的页面标题,使用中间杠()来替换特殊字符及空格。这里页面句柄为learning-about-the-page-handle

如果出于某种原因,我们要修改之前创建的页面标题,仅会影响到页面的标题。句柄保持不变,因为修改页面名称不会自动更新句柄。修改句柄的唯一方式是点击Edit website SEO并手动编辑URL and handle字段中的句柄。

既然我们已经学习了页面句柄是什么以及如何进行管理,下面就继续讲解EmptyDrop数据类型剩下的学习。

EmptyDrop数据类型

前文说过EmptyDrop是由于访问已删除或已禁用对象的属性所导致的。注意EmptyDrop类似nil,不是一个文本为EmptyDrop的字符串或者变量,因此没有什么视觉表现。

我们可以把所访问的对象名变成复数,后接中括号([]) 或点号标记(.)来访问对象的句柄:

虽然不论选取哪种标记法结果都相同,但很有必要提出,因为目的不同,在本文后面会讲到:

我们学习了如何访问对象并通过页面句柄读取其属性。但如果进入到管理后台并通常将Visibility选择切换为Hidden,禁用掉之前所创建的页面呢?这样就会产生EmptyDrop:

EmptyDrop仅有一个名为empty的属性,总是返回真。要避免这一个问题,我们可以创建条件语句来检测EmptyDrop是否为empty

如果该对象不等于empty(对EmptyDrop总是会返回真),条件语句中的代码会进行渲染。否则如果等于empty,所查找的对象为empty,代码不进行渲染。

对空白的控制

上一部分中我们学习了如何使用带有变量数据类型的条件语句来确保总是接收正确的值。但即使用这种条件语句,一些值可能携带多余的空白:

本例中,我们创建一个在集合对象存在时返回true的条件语句,以保障不会出现不完整的消息。虽然结果看上去是对的,但查看页面元素的话,会发现结果并不完美:

从例中可以看出,我们成功地获取了集合信息。但是,在Liquid所处理得到的消息周围存在多余的空格。虽然不是所有的Liquid代码都会输出HTML,默认每一行Liquid代码都会生成一行。

要解决这一问题,我们可以在语句标签中引入中间杠,如{{- – }} 或 {%- -%},这会去除掉多余的空格:

通过像上面代码块中这样引入中间杠,我们成功地移除了条件语句所渲染的两个空行:

注意条件语句内两端所添加的中间杠删除掉了两边的空白。但我们仅在collection.title的闭合括弧端加了一个中间杠,用于移除右侧的空格。如果在左侧加添加了中间杠,会删除掉 is 与集合名词之间的空格。

小结

本文中我们学习了什么是Liquid、Liquid的基础知识,并通过学习如何阅读和编写其语句来识别Liquid代码。我们对Liquid的所有逻辑和比较运算符建立了了解,结合文中所讲解的所有Liquid数据类型,可以帮助我们仅接收到所希望得到的数据。在不断学习的过程中,这会变量越来越基础。

最后,我们学习了如何单独创建、访问每个页面,对于后续文章的学习会非常有用,在后续文章中我们会更深入地学习本文中出现的对象。

知识巩固

  1. 如果希望输出为结果我们该使用哪种定界符?
  2. 以下条件语句会产生什么结果,为什么?
  3. 访问属性内子项的两个方法是什么?
  4. 使用句柄访问对象的正确方式是什么?
  5. 以下代码块中存在的两具问题是什么?
退出移动版