Vue:Vdom与组件

本文详细介绍了Vue中的虚拟DOM及其使用流程,包括数据获取、VDOM创建、render函数、diff算法和key的验证。此外,文章还讨论了Vue的两大特性——指令和组件,特别是组件的创建、复用规则以及is规则的应用。

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

虚拟dom && diff算法

虚拟dom是什么?

它是一个Object对象模型,用来模拟真实dom节点的结构

虚拟dom的使用基本流程

获取数据( ajax fetch )
var data = {
      id: 1,
      name: 'XXXX'
    }
创建vdom
<div class = "box">
        <ul>
          <li> {{ data.name }} </li>
        </ul>
      </div>
通过render函数解析jsx,将其转换成 vdom结构
var vdom = {
      tag: 'div',
      attr: {
        className: 'box'
      },
      content: [
        {
          tag: 'ul',
          content: [
            {
              tag: 'li',
              content: data.name
            }
          ]
        }
      ]
    }
将vdom渲染成真实dom(render函数)
数据更改
data.name = 'ZZZZ'
 vdom = {
      tag: 'div',
      attr: {
        className: 'box'
      },
      content: [
        {
          tag: 'ul',
          content: [
            {
              tag: 'li',
              content: data.name
            }
          ]
        }
      ]
    }
使用diff算法比对两次vdom,生成patch对象
根据key将patch对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的( 虚拟dom的惰性原则 )

什么是jsx?

  • jsx javascript + xml

diff算法是什么?

diff算法是比较两个文件的差异,并将两个文件不同之处,将这个不同之处生成一个补丁对象(patch) 
diff算法来源后端
前端将其应用于虚拟dom的diff算法
vue中将 虚拟dom的diff算法放在了   patch.js文件中 
使用js来进行两个对象的比较( vdom 对象模型)
diff算法是同级比较
给每一个层级打一个标记,这个标记是一个数字( 这个数字就是 key  )

注意: vue是一是MVVM框架,Vue高性能的原因之一就是vdom

验证 key

  • 列表循环一定加key
  • key最好是使用具有唯一标识性的 id

为什么列表循环要加key ?

  • 在Vue中,存在一个DOM复用机制,会尽量的回收DOM元素进行复用,而这个机制本身是高效的,但很多时候也会造成不可预知的Bug,而在加了key值后,元素就有了一个标识,复用机制不会复用带key值的元素。而React也存在类似的机制。
  • 反之,若使用相同的key值,可以使组件复用,也有可能导致渲染内容缺失。
  • 因此,key值一般来说,最好是独一无二的。
  • 除此之外,虚拟DOM在使用Diff算法进行对比时,若存在key值,可以更高效更迅速。

Vue有两大特性

指令 – 用来操作dom

组件 – 组件是html css js 等的一个聚合体

为什么要使用组件?
  1. 组件化
    1. 将一个具备完整功能的项目的一部分进行多处使用
    2. 加快项目的进度
    3. 可以进行项目的复用
  2. 要想实现组件化,那么我们使用的这一部分就必须是完整的,我们把这个完整的整体就称之为组件
  3. 插件: index.html img css js
  4. 如果能将 html css js img 等多个部分放在一起,那该有多好,vue将这个聚合体的文件称之为,单文件组件( xx.vue )
基础的组件创建
  1. 全局注册

     var Hello = Vue.extend({
        template: '<div> 这里是father组件 </div>'
      })             //VueComponent( option )
    
      Vue.component( 'Father', Hello )
    
      new Vue({
        el: '#app'
      })
    
  2. 局部注册

      var Hello = Vue.extend({
        template: '<div> 这里是XXXX </div>'
      })
    
      new Vue({
        el: '#app',
        components: {
          // key: value  key是组件名称   value是组件配置项
          // 'val': Hello,
          'val': Hello
        }
      })
    
    
      new Vue({
        el: '#root'
      })
    
  3. 组件的嵌套

      /* 
        组件的嵌套
            父组件里面放子组件 ----》 类似于dom结构的父子级结构
    
            将子组件以标签的形式放在父组件的模板中使用
    
    
            切记,不要放在父组件的内容中
    
    
            组件不仅可以用双标签表示,也可以使用单标签表示
      */
    new Vue({
        el: '#app',
        components: {
          'Father': {
            template: '<div> father组件 <Son /></div>',
            components: {
              'Son': {
                template: '<div> son组件 </div>'
              }
            }
          }
        }
      })
    
关于组件
  1. vue是如何扩展组件的?

    extends方法 https://cn.vuejs.org/v2/api/#extends

  2. vue为什么要以标签的形式使用组件

    Vue不进行 实例化 Vue.extend(),vue借鉴了react,react中组件是以标签的形式使用的.

  3. 组件使用为何要注册

    为了符合 html / html5的规则,所以组件的标签化使用必须注册

组件的一些特殊使用规则 【 is 规则】
  /* 
    is规则
      ul>li  ol>li   table>tr>td      select>option

    如上直属父子级如果直接组件以标签化形式使用,那么就会出现bug

    解决: 使用is规则: 通过is属性来绑定一个组件
     <tr is = "Hello"></tr>

    案例: table
  */
 <div id="app">
    <table>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr is = "Hello"></tr>
    </table>
  </div>
---------------------------------------javascript-------------------------------------
  Vue.component('Hello',{
    template: '<tr> <td> 4 </td> <td> 2 </td><td> 3 </td></tr>'
  })

  new Vue({
    el: '#app'
  }) 	
组件的template
 /* 
    template使用: 
        1. 实例范围内使用
          template中的内容被当做一个整体了,并且template标签是不会解析到html结构中的
        2. 实例范围外使用
          实例范围外template标签是不会被直接解析的

    组件要想使用template使用,我们采用第二种

    但是使用第二种template使用后,有个弊端,template标签结构会在html文件中显示

    解决: 使用webpack、gulp等工具编译,将来要用vue提供的单文件组件
   */
--------------------------------------------------------------------------------------
   <div id="app">
    <h3> 实例范围内使用 </h3>
    <template>
      <div>
        <ul>
          <li>1</li>
          <li>2</li>
          <li>3</li>
        </ul>
      </div>
    </template>


    <h3> 使用 hello  组件</h3>

    <Hello></Hello>

  </div>
  <h3> 实例范围外使用 </h3>
  <template id="hello">
    <div>
      <ul>
        <li>1</li>
        <li>2</li>
      </ul>
    </div>
  </template>
---------------------------------------javascript-------------------------------------
   Vue.component('Hello',{
    template: '#hello'
  })

  new Vue({
    el: '#app'
  })
出现这个错误的原因是在导入seaborn包时,无法从typing模块中导入名为'Protocol'的对象。 解决这个问题的方法有以下几种: 1. 检查你的Python版本是否符合seaborn包的要求,如果不符合,尝试更新Python版本。 2. 检查你的环境中是否安装了typing_extensions包,如果没有安装,可以使用以下命令安装:pip install typing_extensions。 3. 如果你使用的是Python 3.8版本以下的版本,你可以尝试使用typing_extensions包来代替typing模块来解决该问题。 4. 检查你的代码是否正确导入了seaborn包,并且没有其他导入错误。 5. 如果以上方法都无法解决问题,可以尝试在你的代码中使用其他的可替代包或者更新seaborn包的版本来解决该问题。 总结: 出现ImportError: cannot import name 'Protocol' from 'typing'错误的原因可能是由于Python版本不兼容、缺少typing_extensions包或者导入错误等原因造成的。可以根据具体情况尝试上述方法来解决该问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ImportError: cannot import name ‘Literal‘ from ‘typing‘ (D:\Anaconda\envs\tensorflow\lib\typing....](https://blog.youkuaiyun.com/yuhaix/article/details/124528628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值