从头设计Web前端开发框架(二): 虚拟DOM设计

本文围绕jm-hcj前端框架展开,介绍了虚拟DOM标签设计构想,包括DOM树语法构成、变量作用域。还阐述了JM表达式、分支语法、循环语法、变量操作语法、渐进式属性定义及Ajax支持等内容,旨在让前端代码更结构化,减少不必要的JS定义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言        

        一个Web前端框架最先被使用者感知的大概就是虚拟DOM的标签和语法了,为什么叫虚拟DOM呢,因为通常基于Web前端框架编写的DOM包含很多框架自定义的标签,这些标签能够极大简化DOM的结构,但并不能被浏览器有效处理,这些DOM结构只有经过框架引擎翻译渲染后才能被转换为真正的DOM结构并被浏览器识别。

        那么jm-hcj实质设计的第一步,就是设计虚拟DOM标签了。对于这个问题,一直以来我都有一个疯狂的想法,我希望能够像写其它编程语言代码一样,让HTML编写变得有逻辑,而不仅仅是结构定义,甚至,让HTML标签更多的替代JS。例如让HTML标签能够在一定的作用域中定义变量、加载数据甚至进行基本的数据加工。

        那么,就把这个想法在jm-hcj上实现吧。

一、总体构想

1.1 DOM树的语法构成

        jm-hcj的虚拟DOM部分实际应该分成两个部分,分别是 基于HTML扩展的特殊含义标签 和 标签相关的特殊含义属性

        对于框架而言,无论是特殊含义的标签还是属性,都应当支持持续扩展,而不应当封闭。我们把jm-hcj默认定义的特殊含义标签称为语法标签,把特殊含义属性称为语法属性。语法标签和语法属性应是两个彼此独立的集合,语法标签可以配套定义自身的属性,但这些配套定义的属性应视为语法标签的组成部分,而不是语法属性,而语法属性应当可以广泛应用于绝大部分标签,并具备独立功能。

        语法标签语法属性共同构成了虚拟DOM树的语法(实际叫语法不是很严谨,但为了方便就这么叫吧)。虚拟DOM树的语法应尽可能符合HTML编写规范,这样就能够方便的在各类IDE中开发,且能够被正确的着色。

1.2 基于虚拟DOM树的变量作用域

1.2.1 数据交互是前端一直的痛

        对于一个熟练的前端开发人员来说,开发页面最麻烦的部分就是与后端的数据交互,“对接口”头疼的原因是需要不断的处理加载时序、与插值对应等问题。

        传统的虚拟DOM树的渲染过程可以简单描述为通过给定的初始数据(data),对DOM模板(一个包含HTML定义的字符串)中的插值进行替换,如果在渲染过程中需要对data的内容进行增补或修改,需要在对应的JS钩子方法中完成。

        例如,假设在某网站首页加载时,需要分三步完成个人信息数据的展示:

        1.通过 /api/account/summary 接口加载当前登录用户信息,用户信息内包含用户的uid,在页面上显示用户姓名;

        接口返回数据示例:

{
    uid : "xxxx-xxxx",
    name : "张三"
}

        2.以uid为参数,通过接口 /api/vip/level?uid= 获取用户的VIP等级信息,展示VIP等级;

      接口返回数据示例:

{
    level : 3,
    expiringTime : "2024-12-31"
}

     3. 根据用户uid和vip等级,通过/api/content/individual 拉取面向该用户的推荐内容,并在页面上以列表形式展示。

接口返回数据示例:

[
    {"title" : "推荐内容1", "url" : "xxx.com/article/100001"},
    {"title" : "推荐内容2", "url" : "xxx.com/article/100002"},
    {"title" : "推荐内容3", "url" : "xxx.com/article/100003"},
]

         针对这种需求,相当多的Vue开发者会给出两种解决方案,一是定义三个组件,逐层嵌套,在每个组件的created()钩子中完成一次接口数据拉取,把结果传递给子组件,每个组件分别渲染自身的内容;二是定义一个组件,在created中依次调用三个API,并且把三个结果全部放入data中,一次性完成渲染。例如:

<!-- Vue实现示例 -->

<template>

    <div class="individual">
        <span class="name">{
  
  {userName}}</span>
        <span class="vip">VIP(Lv.{
  
  {vipLevel}})</span>
    </div>

    <div class="articles">
        <ol>
            <li v-for="article in articles">
                <a href="{
  
  {article.url}}">{
  
  {article.title}}</a>
            </li>
        </ol>
    </div>

</template>

<script>
    // 简化代码,仅用于示例
    export default {
        data(){return {}},

        mounted(){
            this.fetchData();
        },

        methods:{
            async fetchData() {
                let individualSummary = await axios.get("/api/individual/summary");
                this.name = individualSummary.name;

                let uid = individualSummary.uid;
                let vipLevel = await axios.get("/api/vip/level?uid=" + uid);
                this.vipLevel = vipLevel.level;

                let url = "/api/content/indi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值