webapck搭建環境,讓你知道vue中的h函數的作用和虛擬節點如何上樹!

搭建環境

npm init 初始化項目
npm i -D snabbdom 安裝
npm i -D webpack@5 webpack-cli@3 webpack-dev-server@3 

簡單介紹

snabbdom 是一個DOM庫.[重要]
不能夠直接運行在Node環境中,
我們需要搭建一個webpack和webpack-dev-server的開發環境
需要注意的是必須安裝webpck5. 不能夠安裝webpack4.
因為webpck4中沒有讀取 exports的能力哈
然後安裝:目的是搭建開發的運行環境

npm i -D webpack@5 webpack-cli@3 webpack-dev-server@3 
這個千萬不忘記配置呀

創建 webpack.config文件

//這個webpack.config文件在項目的根目錄下
// 安裝官網配置直接複製 //webpack.js.org/ 然後做簡單的修改
const path = require('path');
module.exports = {
    // 入口,需要靠你去創建
    entry: './src/index.js',
    // 出口
    output: {
      // path: path.resolve(__dirname, 'dist'),
      //虛擬的打包路徑 也就是說文件夾不會真正的生成,而是在8080埠虛擬生成的
      // xuni 這個不會真正的生成,在記憶體中,打包後的文件名是 bundle
      publicPath:'xuni', 
      filename: 'bundle.js',
    },
    <!-- 配置的是 開發服務 -->
    devServer: {
        port: 8080, //埠
        // 靜態資源文件夾,你創建一個,跟src 同級,
        contentBase:'www'
    }
};

需要創建的文件

根據上面的配置要求。
我們需要在項目的跟目錄下創建 src文件夾,src下有index.js文件
我們需要在項目的跟目錄下創建 www文件夾,src下有index.html文件

我們在index.js文件中寫
console.log("你好啊,環境已經搭建ok,我好高興")
這個文件打包後對應的虛擬文件是bundle.js

我們在index.html文件中寫
<body>
  <h1>你好啊!</h1>
  <!-- 
    這個container 在我們等會使用snabbdom的時候需要,
    我們現在就將他創建好
    -->
  <div id="container"></div>
</body>

<!--
 bundle.js 是我們生成在記憶體中的,在物理上看不見。
 我們等會寫的xuni/bundle.js 是打包後的。
 它打包前的是 src下有index.js文件
 -->
<script src="xuni/bundle.js"></script>
</html>

更改 package.json 文件配置

在package.json文件中。
我們需要更改一下配置
"scripts": {
   "test": "echo \"Error: no test specified\" && exit 1"
},
更改為
  "scripts": {
  "dev": "webpack-dev-server"
},
這樣我們執行 npm  run dev 就會將,
我們下載的 webpack-dev-server服務啟動起來

然後簡單去走一下 snabbdom的流程

snabbdom的地址://github.com/snabbdom/snabbdom 
複製Example。到我們的 index.js文件中

我們會發現有
const container = document.getElementById("container");
所以我們需要在index.html中去創建
這就解釋了為啥我們的index.html需要有一個id為container
不過我們剛剛已經創建了

然後我們會發現有兩個函數報錯 someFn is not  undefined
anotherEventHandler is not  undefined
我們將這兩個函數更改為普通函數 就ok了

index.js簡單使用h函數

import {
  init,
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
  h,
} from "snabbdom";

let myVnode1 = h
(
  'a', 
  { props:
    { href: '//www.cnblogs.com/IwishIcould/' }
  },
  '我的部落格'
)
console.log("myVnode1", myVnode1) //輸出來的內容就是虛擬dom節點
這行程式碼說明了: h函數產生虛擬dom節點

區別

<div>
    <p>123</p>
</div>
轉化為這個
let obj={
  'tag':'div',
  'child':[
      'tag':'p',
      'text':'123'
  ]
}
不是h函數做的。
而是模板編譯原理做的

使用patch函數讓虛擬dom節點上樹

import {
  init,
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
  h,
} from "snabbdom";

let myVnode1 = h('a', { props: { href: '//www.cnblogs.com/IwishIcould/' } }, '我的部落格')
console.log("myVnode1", myVnode1) //輸出來的內容就是虛擬dom節點

// 使用init函數創建 patch函數 
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 讓虛擬節點上樹
patch(container,myVnode1)

init函數創建patch函數

使用init函數創建patch函數 ,init函數接受4個參數。
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
[類模組,屬性模組,style模組,事件模組 ]

patch函數讓虛擬dom節點上樹

// 讓虛擬節點上樹
patch(container,myVnode1)
patch函數接受兩個參數,上樹到哪一個容器下,上樹的虛擬節點

一個容器讓多個虛擬節點上樹,可以使用h函數的嵌套

let myVnode1 = h('ul', {}, [
  h('li', {}, '姓名'),
  h('li', {}, '年齡'),
  h('li', {}, '愛好'),
])
console.log("myVnode1", myVnode1) //輸出來的內容就是虛擬dom節點

// 使用init函數創建 patch函數 
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 讓虛擬節點上樹
patch(container, myVnode1)
console.log("上樹後", myVnode1) //輸出來的內容就是虛擬dom節點