0

0

聊聊Angular中的模板输入变量(let-变量)

青灯夜游

青灯夜游

发布时间:2021-07-14 10:40:31

|

2367人浏览过

|

来源于掘金社区

转载

聊聊Angular中的模板输入变量(let-变量)

我这个人,写文章或者说心得,不喜欢直接抄官网上面的东西,实在是没啥意思。我还是喜欢用我的大白话来写文章。今天这个关于模板输入变量的这个我今天啃官网啃了许久,总算是初步的了解了是啥东西。【相关教程推荐:《angular教程》】

那么模板输入变量到底是什么

我想研究这玩意的起因在于之前我使用ng-zorro的时候,用到了它的分页组件Pagination官网链接)。这其中有一个自定义上一页下一页模板的功能。代码的话如下:

@Component({
  selector: 'nz-demo-pagination-item-render',
  template: `
    
    
      
        {{ page }}
        Previous
        Next
        <<
        >>
      
    
  `
})
export class NzDemoPaginationItemRenderComponent {}

看完这个之后我就很是疑惑,这个let是啥,为啥let-跟上一个变量之后就有值了呢?然后我就开始在官网中找这个let是什么东西。最终,我在主要概念-指令-结构性指令微语法一节找到了关于let的说明。官网描述:微语法

在下面还有一段简短的说明:

模板输入变量(Template input variable)模板输入变量是这样一种变量,你可以在单个实例的模板中引用它的值。 这个例子中有好几个模板输入变量:hero、i 和 odd。 它们都是用 let 作为前导关键字。......你使用 let 关键字(如 let hero)在模板中声明一个模板输入变量。 这个变量的范围被限制在所重复模板的单一实例上。 事实上,你可以在其它结构型指令中使用同样的变量名。......

官网还是一如既往的不说人话,短短几句话就给你介绍完了,也不告诉你这玩意怎么用,也不告诉你let声明的变量的值到底是从哪里来的。我越看越气,得,官网你不说,我自己找。

先说一个粗略的结论:let声明的变量是这个template模板的上下文对象中的变量。不然为啥叫模板输入变量呢。在*ngFor内幕这小节中,我们了解到了其内幕,结构性指令其实就是将宿主元素包裹在一个中,然后在这个模板上将*ngFor中的表达式解析成一个个的let模板输入变量和这个指令需要传入的值。由于模板中代码并不会直接被渲染成视图,所以一定需要某种方法来使模板变成视图。我们的结构性指令就是干这个事的,就是将我们的模板变成视图。

*ngFor的官方示例代码如下:

//解析前的模板
({{i}}) {{hero.name}}
//angular解析后的模板
({{i}}) {{hero.name}}
  • 在此提示一下,所谓的宿主元素就是指令所在的那个元素,像上面的例子中,div就是*ngFor指令的宿主元素。
  • trackBy这个类似于vue和react中的key。可以给模板一个标识,使其重新渲染的时候性能开销降低一些。

然后我们再看官网说的:

  • let-ilet-odd 变量是通过 let i=indexlet odd=odd 来定义的。 Angular 把它们设置为上下文对象中的 indexodd 属性的当前值。
  • 这里并没有指定 let-hero 的上下文属性。它的来源是隐式的。 Angular 将 let-hero 设置为此上下文中 $implicit 属性的值, 它是由 NgFor 用当前迭代中的英雄初始化的。

看完这段描述,我们可以得知:angular为这个模板设置了上下文对象。但是我们看不到这个过程,因为这是在ngFor的源码内部实现的。并且这个上下文对象具备indexodd属性,并且包含一个$implicit(implicit:含蓄的;不直接言明的)的属性。那么我们推断这个上下文对象至少有以下几个属性:

{
    $implicit:null,
    index:null,
    odd:null,
}

那么我们声明let变量的本质其实就是声明一个变量获取上下文对象中的同名属性的值let-hero不进行任何赋值的话,hero默认等于$implicit的值。无论是有多少个let-alet-blet-c还是let-me。声明的这个变量的值都等于$implicit的值。而我们进行赋值过的,比如let-i = "index"i的值就等于这个上下文对象中的index属性对应的值。

上下文对象是如何设置的

当我们知道这个上下文对象是什么了,就该想这个上下文对象是怎么设置的了

结构性指令这一节当中,我们跟着官方示例做了一遍这个自定义结构性指令(如果还没有做的话,建议先跟着做一遍)。在UnlessDirective这个指令中,其构造器constructor声明了两个可注入的变量,分别是TemplateRefViewContainerRef。官网给的解释我觉得太过晦涩难懂,我这里给出一下我自己的理解:TemplateRef代表的是宿主元素被包裹之后形成的模板的引用。而ViewContainerRef代表的是一个视图容器的引用。那么问题来了,这个视图容器在哪儿呢?我们在constructor构造器中打印一下ViewContainerRef。打印结果如图:

1.png

然后我们点进去这个comment元素。发现其就是一个注释元素。如图所示:

2.png

其实我也不是很确定这个视图容器到底是不是这个注释元素。但是毋庸置疑的是,视图容器和宿主元素是兄弟关系,紧挨着宿主元素。我们可以使用ViewContainerRef中的createEmbeddedView() 方法(Embedded:嵌入式,内嵌式),将templateRef模板引用传入进去,创建出来一个真实的视图。由于这个视图是被插入到视图容器ViewContainerRef中了,所以又叫内嵌视图。那么这又和我们的上下文对象有什么关系呢?其实createEmbeddedView这个方法不止一个参数,其第二个参数就是给我们的模板设置上下文对象的。API的详情介绍请看createEmbeddedView这个API的详情

艾绘
艾绘

艾绘:一站式绘本创作平台,AI智能绘本设计神器!

下载

3.png

就这样。我们就可以将上下文对象塞入模板中了,这样的话我们也可以直接使用let声明变量的方法来使用这个上下文对象了。

自定义一个简单的类*ngFor指令——appRepeat

那么我们知道是如何设置的了,那么我们就来验证一下是否是对的。接下来,我们仿照ngfor的功能,自己写一个简单的渲染指令。

首先我们定义一个指令:RepeatDirective。代码如下:

@Directive({
  selector: '[appRepeat]',
})
export class RepeatDirective {
  constructor(
    private templateRef: TemplateRef,
    private viewContainer: ViewContainerRef,
  ) { }

  @Input() set appRepeatOf(heroesList: string[]) {
    heroesList.forEach((item, index, arr) => {
      this.viewContainer.createEmbeddedView(this.templateRef, {
        //当前条目的默认值
        $implicit: item,
        //可迭代对象的总数
        count: arr.length,
        //当前条目的索引值
        index: index,
        //如果当前条目在可迭代对象中的索引号为偶数则为 true。
        even: index % 2 === 0,
        //如果当前条目在可迭代对象中的索引号为奇数则为 true。
        odd: index % 2 === 1,
      });
    });
  }
}

然后我们将其导入NgModule中,这个过程就省略不写了。然后我们在组件中使用一下这个指令:

@Component({
  selector: 'app-structural-likeNgFor-demo',
  template: `
    

原神1.5版本卡池角色

自定义ngFor(appRepeat)

  • 索引:{{i}} -- {{h}} -- 索引值是否是偶数:{{even.toString()}}

真正的ngFor

  • 索引:{{i}} -- {{h}} -- 索引值是否是偶数:{{even.toString()}}
`, }) export class StructuralLikeNgForDemoComponent { public heroesList: string[] = ['钟离', '烟绯', '诺艾尔', '迪奥娜']; }

在这里需要注意的是指令中的appRepeatOf不是乱写的。在微语法的解析过程中let h of heroesList中的of首先首字母会变成大写的,变成Of。然后在给它加上这个指令的前缀,也就是appRepeat。组合起来就是appRepeatOf了。由它来接收一个可迭代的对象。

最后显示的效果图:

4.png

运行结果的话和*ngFor没有区别。但是功能肯定是欠缺的,如果有能力的小伙伴可以去阅读*ngFor的源码:*ngFor的源码

总结

通过这篇文章,我们知道了let-变量这个模板输入变量是通过模板的上下文对象中定义并获取值的。然后想要设置上下文对象的话需要通过createEmbeddedView方法的第二个参数来设置。

结语

但是我总觉得了解的还不够透彻,我总觉得设置模板的上下文对象可能不只是createEmbeddedView这一种方法,但是我并没有找到其他的方法。如果各位小伙伴有知道其他的方法可以留言告诉我。

参考资料:

这篇文章灵感来自:Angular 实现一个"repeat" 指令

转载地址:https://juejin.cn/post/6956466729891561503

更多编程相关知识,请访问:编程入门!!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

178

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

35

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

79

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

2

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

4

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

8

2026.01.28

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

24

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

122

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

72

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue.js:纪录片
Vue.js:纪录片

共1课时 | 0.2万人学习

Angular js入门篇
Angular js入门篇

共17课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号