Vue的基礎知識(三)

来源:https://www.cnblogs.com/xyh9039/archive/2023/02/26/17139196.html
-Advertisement-
Play Games

本章將繼續和大家分享Vue的一些基礎知識。話不多說,下麵我們直接上代碼: 本文內容大部分摘自Vue的官網:https://v2.cn.vuejs.org/v2/guide/ 首先我們先來看一下Demo的目錄結構,如下所示: 一、偵聽器 <!DOCTYPE html> <html lang="en"> ...


本章將繼續和大家分享Vue的一些基礎知識。話不多說,下麵我們直接上代碼:

本文內容大部分摘自Vue的官網:https://v2.cn.vuejs.org/v2/guide/

首先我們先來看一下Demo的目錄結構,如下所示:

一、偵聽器

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue中的偵聽器</title>
    <script src="/js/lib/vue.js"></script>
    <script src="/js/lib/axios.js"></script>
    <script src="/js/lib/lodash.js"></script>
</head>

<body>
    <div id="app">
        <div desc="偵聽屬性">
            <p>
                請輸入您的問題:
                <input v-model="question">
            </p>
            <p>{{ answer }}</p>
        </div>
    </div>

    <script>
        var vm = new Vue({
            el: '#app', //掛載點
            data: {
                question: '',
                answer: '在您提出問題之前,我不能給您答案!',
                student: {
                    name: '張三',
                    age: 18
                }
            },
            watch: {
                //簡單監聽
                //如果 `question` 發生改變,這個函數就會運行
                question: function (newQuestion, oldQuestion) {
                    var _this = this;
                    _this.answer = '正在等待您停止輸入...'
                    _this.debouncedGetAnswer();
                },
                //對對象進行深度監聽
                //普通的watch方法無法監聽到對象內部屬性的變化
                student: {
                    handler(newValue, oldValue) {
                        // 註意:在嵌套的變更中,
                        // 只要沒有替換對象本身,
                        // 那麼這裡的 `newValue` 和 `oldValue` 相同,都是新值
                        console.log(newValue);
                        console.log(oldValue);
                    },
                    deep: true, // 深度監聽
                    immediate: true // 強制立即執行回調(一般用於父組件向子組件動態傳值時)
                },
                //對對象的某一個屬性進行深度監聽
                //如果想要監聽對象的某一個屬性,並且希望獲取該屬性變化前後的值則需要用該方式進行監聽
                'student.age': {
                    handler(newValue, oldValue) {
                        console.log(newValue);
                        console.log(oldValue);
                    },
                    deep: true, // 深度監聽
                    immediate: true // 強制立即執行回調(一般用於父組件向子組件動態傳值時)
                }
            },
            created: function () {
                // `_.debounce` 是一個通過 Lodash 限制操作頻率的函數。
                // 在這個例子中,我們希望限制訪問 介面 的頻率
                // AJAX 請求直到用戶輸入完畢才會發出。想要瞭解更多關於
                // `_.debounce` 函數 (及其近親 `_.throttle`) 的知識,
                // 請參考:https://lodash.com/docs#debounce
                var _this = this;
                _this.debouncedGetAnswer = _.debounce(_this.getAnswer, 1500); //debouncedGetAnswer 方法名可自定義
            },
            methods: {
                getAnswer: function () {
                    var _this = this;
                    if (_this.question.indexOf('?') === -1) {
                        _this.answer = '問題通常包含問號!';
                        return;
                    }

                    _this.answer = '數據獲取中...';
                    axios.get('https://autumnfish.cn/api/joke')
                        .then(function (response) {
                            _this.answer = response.data;
                        })
                        .catch(function (error) {
                            _this.answer = '請求介面異常:' + error;
                        });
                }
            }
        });
    </script>
</body>

</html>

二、Vue組件基礎

自定義組件 <button-counter> 代碼如下:

define([
    'axios'
], function (axios) {
    /*
        因為組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命周期鉤子等。
        僅有的例外是像 el 這樣根實例特有的選項。
    */
    return {
        template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
        props: [],
        //一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝
        data: function () {
            return {
                count: 0
            }
        },
        mounted: function () {

        },
        methods: {

        },
        watch: {

        }
    };
});

自定義組件 <blog-post> 代碼如下:

define([
    'axios'
], function (axios) {
    /*
        因為組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命周期鉤子等。
        僅有的例外是像 el 這樣根實例特有的選項。
    */
    return {
        //每個組件必須只有一個根元素
        template: `
            <div class="blog-post" desc="根元素">
                <h3>{{ post.title }}</h3>
                <p>子組件中的titleNew:<input type="text" v-model="titleNew"></p>
                <slot></slot>
                <button @click="handleEnlargeText">Enlarge text</button>
                <div v-html="post.content"></div>
            </div>
        `,
        /*
            1、通過 Prop 向子組件傳遞數據。
            2、一個組件預設可以擁有任意數量的 prop,任何值都可以傳遞給任何 prop。
               在上述模板中,你會發現我們能夠在組件實例中訪問這個值,就像訪問 data 中的值一樣。
            3、所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。
               這樣會防止從子組件意外變更父級組件的狀態,從而導致你的應用的數據流向難以理解。
        */
        props: ['post', 'title'],
        //一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝
        data: function () {
            return {
                enlargeFontSize: 0.1, //需要放大字體的大小
                titleNew: this.title, //初始值為props中父組件傳遞過來的值
            }
        },
        mounted: function () {

        },
        methods: {
            //處理放大文本字體
            handleEnlargeText: function () {
                var _this = this;
                //子組件可以通過調用內建的 $emit 方法並傳入事件名稱來觸發一個父組件的事件
                //第二個參數為調用父組件事件所需傳的參數
                //enlarge-text為自定義事件
                _this.$emit('enlarge-text', _this.enlargeFontSize);
            }
        },
        watch: {
            //監聽器完整寫法
            title: {
                handler(newValue, oldValue) {
                    this.titleNew = newValue;
                },
                //deep: true, // 深度監聽
                immediate: true // 強制立即執行回調(一般用於父組件向子組件動態傳值時)
            },
            //監聽器簡寫,當需要設置 deep 或者 immediate 時需使用完整寫法
            titleNew: function (newValue, oldValue) {
                /*
                    註意在 JavaScript 中對象和數組是通過引用傳入的,所以對於一個數組或對象類型的 prop 來說,
                    在子組件中改變變更這個對象或數組本身將會影響到父組件的狀態。
                    這種情況下就不需要以 update:myPropName 的模式觸發更新事件了。
                */
                this.$emit('update:title', newValue); //更新父組件title屬性綁定的值
                /*
                    自定義事件 .sync 修飾符:
                    在有些情況下,我們可能需要對一個 prop 進行“雙向綁定”。
                    不幸的是,真正的雙向綁定會帶來維護上的問題,因為子組件可以變更父組件,且在父組件和子組件兩側都沒有明顯的變更來源。

                    這也是為什麼我們推薦以 update:myPropName 的模式觸發事件取而代之。
                    舉個例子,在一個包含 title prop 的假設的組件中,我們可以用以下方法表達對其賦新值的意圖:
                    this.$emit('update:title', newTitle)

                    然後父組件可以監聽那個事件並根據需要更新一個本地的數據 property。例如:
                    <text-document
                        v-bind:title="doc.title"
                        v-on:update:title="doc.title = $event">
                    </text-document>

                    為了方便起見,我們為這種模式提供一個縮寫,即 .sync 修飾符:
                    <text-document :title.sync="doc.title"></text-document>
                */
            }
        }
    };
});

Vue組件基礎.html 代碼如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue組件基礎</title>
</head>

<body>
    <div id="app">
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>

        <div :style="{ fontSize: postFontSize + 'em' }">
            <blog-post v-for="post in posts" :key="post.id" :title.sync="post.title" :post="post"
                v-on:enlarge-text="onEnlargeText">
                <!-- 預設插槽的內容 -->
                <template v-slot:default>
                    <p>父組件中的post.title:<input type="text" v-model="post.title" /></p>
                </template>
            </blog-post>
        </div>
    </div>

    <script src="/js/lib/require.js"></script>
    <script src="/js/common/require_config.js"></script>
    <script src="/js/ComponentsDemo.js"></script>
</body>

</html>

其中 ComponentsDemo.js 代碼如下:

//Vue組件基礎
require(['../common/base', '../components/blogPost'], function (base, blogPost) {
    let axios = base.axios;

    var vm = new base.vue({
        el: '#app', //掛載點
        mixins: [base.mixin], //混入,類似基類的概念
        components: {
            'blog-post': blogPost //局部註冊組件,註意局部註冊的組件在其子組件中不可用。
        },
        data: {
            posts: [
                { id: 1, title: 'My journey with Vue' },
                { id: 2, title: 'Blogging with Vue' },
                { id: 3, title: 'Why Vue is so fun' }
            ],
            postFontSize: 1
        },
        //created鉤子函數
        created: function () {
            console.log('This is index created');
        },
        //mounted鉤子函數
        mounted: function () {
            console.log('This is index mounted');
        },
        //方法
        methods: {
            //放大文本
            onEnlargeText: function (enlargeFontSize) {
                var _this = this;
                _this.postFontSize += enlargeFontSize
            }
        }
    });
});

其中 require_config.js 代碼如下:

//主要用來配置模塊的載入位置(設置短模塊名)
require.config({
    baseUrl: '/js/lib', //設置根目錄
    paths: { //如果沒有設置根目錄則需要填寫完整路徑
        'vue': 'vue',
        'axios': 'axios',
        'jquery': 'jquery-3.6.3',
        //paths還有一個重要的功能,就是可以配置多個路徑,如果遠程cdn庫沒有載入成功,可以載入本地的庫,如下:
        //'jquery': ['http://libs.baidu.com/jquery/2.0.3/jquery', '/js/lib/jquery-3.6.3'],
    }
});

其中 base.js 代碼如下:

//define用來自定義模塊
//第一個參數:載入依賴模塊,可以是require_config中定義的短模塊名,也可以是完整的模塊路徑(去掉.js尾碼名)
//第二個參數:執行載入完後的回調函數
define(['vue', 'axios', '../components/buttonCounter'], function (vue, axios, buttonCounter) {
    //TODO 此處可以處理一些公共的邏輯
    //vue.component('component-a', { /* ... */ }); //全局註冊組件
    //vue.mixin({...}); //全局混入

    /*
        定義組件名的方式有兩種:
        1、使用 kebab-case (短橫線分隔命名)
            當使用 kebab-case (短橫線分隔命名) 定義一個組件時,你也必須在引用這個自定義元素時使用 kebab-case,例如 <my-component-name>
        
        2、使用 PascalCase (首字母大寫命名) 
            當使用 PascalCase (首字母大寫命名) 定義一個組件時,你在引用這個自定義元素時兩種命名法都可以使用。
            也就是說 <my-component-name> 和 <MyComponentName> 都是可接受的。
            註意,儘管如此,直接在 DOM (即非字元串的模板) 中使用時只有 kebab-case 是有效的。    
    */

    //Vue.component(...) 的第一個參數為組件名。      
    vue.component('button-counter', buttonCounter); //全局註冊

    return {
        vue: vue,
        axios: axios,

        //Vue混入
        mixin: {
            //數據
            data: function () {
                return {
                    domain: '', //功能變數名稱
                }
            },
            //組件
            components: {

            },
            //created鉤子函數
            created: function () {
                console.log('This is base created');
            },
            //mounted鉤子函數
            mounted: function () {
                console.log('This is base mounted');
            },
            //方法
            methods: {
                //測試
                doTest: function () {
                    console.log('This is base doTest');
                },
                //獲取功能變數名稱
                getDomain: function () {
                    var _this = this;
                    _this.domain = 'https://www.baidu.com';
                },
            }
        },
    };
});

運行結果如下:

三、組件註冊

1、組件名大小寫

定義組件名的方式有兩種:

1)使用 kebab-case

Vue.component('my-component-name', { /* ... */ })

當使用 kebab-case (短橫線分隔命名) 定義一個組件時,你也必須在引用這個自定義元素時使用 kebab-case,例如 <my-component-name>

2)使用 PascalCase

Vue.component('MyComponentName', { /* ... */ })

當使用 PascalCase (首字母大寫命名) 定義一個組件時,你在引用這個自定義元素時兩種命名法都可以使用。也就是說 <my-component-name> 和 <MyComponentName> 都是可接受的。註意,儘管如此,直接在 DOM (即非字元串的模板) 中使用時只有 kebab-case 是有效的。

2、全局註冊 

到目前為止,我們用過 Vue.component 來創建組件:

Vue.component('my-component-name', {
  // ... 選項 ...
})

這些組件是全局註冊的。也就是說它們在註冊之後可以用在任何新創建的 Vue 根實例 (new Vue) 的模板中。

3、局部註冊

全局註冊往往是不夠理想的。比如,如果你使用一個像 webpack 這樣的構建系統,全局註冊所有的組件意味著即便你已經不再使用一個組件了,它仍然會被包含在你最終的構建結果中。這造成了用戶下載的 JavaScript 的無謂的增加。

在這些情況下,你可以通過一個普通的 JavaScript 對象來定義組件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然後在 components 選項中定義你想要使用的組件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

對於 components 對象中的每個 property 來說,其 property 名就是自定義元素的名字,其 property 值就是這個組件的選項對象。

註意局部註冊的組件在其子組件中不可用例如,如果你希望 ComponentA 在 ComponentB 中可用,則你需要這樣寫:

var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'component-a': ComponentA
  },
  // ...
}

四、組件中的Prop

1、Prop 的大小寫 (camelCase vs kebab-case)

HTML 中的 attribute 名是大小寫不敏感的,所以瀏覽器會把所有大寫字元解釋為小寫字元。這意味著當你使用 DOM 中的模板時,camelCase (駝峰命名法) 的 prop 名需要使用其等價的 kebab-case (短橫線分隔命名) 命名:

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

重申一次,如果你使用字元串模板,那麼這個限制就不存在了。

2、Prop 類型

到這裡,我們只看到了以字元串數組形式列出的 prop:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

但是,通常你希望每個 prop 都有指定的值類型。這時,你可以以對象形式列出 prop,這些 property 的名稱和值分別是 prop 各自的名稱和類型:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

這不僅為你的組件提供了文檔,還會在它們遇到錯誤的類型時從瀏覽器的 JavaScript 控制台提示用戶。

3、單向數據流

所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外變更父級組件的狀態,從而導致你的應用的數據流向難以理解。

額外的,每次父級組件發生變更時,子組件中所有的 prop 都將會刷新為最新的值。這意味著你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制臺中發出警告。

這裡有兩種常見的試圖變更一個 prop 的情形:

1)這個 prop 用來傳遞一個初始值;這個子組件接下來希望將其作為一個本地的 prop 數據來使用。

在這種情況下,最好定義一個本地的 data property 並將這個 prop 用作其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

2)這個 prop 以一種原始的值傳入且需要進行轉換。

在這種情況下,最好使用這個 prop 的值來定義一個計算屬性:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

註意在 JavaScript 中對象和數組是通過引用傳入的,所以對於一個數組或對象類型的 prop 來說,在子組件中改變變更這個對象或數組本身將會影響到父組件的狀態。

五、自定義事件

1、事件名

不同於組件和 prop,事件名不存在任何自動化的大小寫轉換。而是觸發的事件名需要完全匹配監聽這個事件所用的名稱。舉個例子,如果觸發一個 camelCase 名字的事件:

this.$emit('myEvent')

則監聽這個名字的 kebab-case 版本是不會有任何效果的:

<!-- 沒有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

不同於組件和 prop,事件名不會被用作一個 JavaScript 變數名或 property 名,所以就沒有理由使用 camelCase 或 PascalCase 了。並且 v-on 事件監聽器在 DOM 模板中會被自動轉換為全小寫 (因為 HTML 是大小寫不敏感的),所以 v-on:myEvent 將會變成 v-on:myevent——導致 myEvent 不可能被監聽到。

因此,我們推薦你始終使用 kebab-case 的事件名

2、.sync 修飾符

在有些情況下,我們可能需要對一個 prop 進行“雙向綁定”。不幸的是,真正的雙向綁定會帶來維護上的問題,因為子組件可以變更父組件,且在父組件和子組件兩側都沒有明顯的變更來源。

這也是為什麼我們推薦以 update:myPropName 的模式觸發事件取而代之。舉個例子,在一個包含 title prop 的假設的組件中,我們可以用以下方法表達對其賦新值的意圖:

this.$emit('update:title', newTitle)

然後父組件可以監聽那個事件並根據需要更新一個本地的數據 property。例如:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

為了方便起見,我們為這種模式提供一個縮寫,即 .sync 修飾符:

<text-document v-bind:title.sync="doc.title"></text-document>

六、插槽

1、具名插槽

有時我們需要多個插槽。例如對於一個帶有如下模板的 <base-layout> 組件:

<div class="container">
  <header>
    <!-- 我們希望把頁頭放這裡 -->
  </header>
  <main>
    <!-- 我們希望把主要內容放這裡 -->
  </main>
  <footer>
    <!-- 我們希望把頁腳放這裡 -->
  </footer>
</div>

對於這樣的情況,<slot> 元素有一個特殊的 attribute:name。這個 attribute 可以用來定義額外的插槽:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

一個不帶 name 的 <slot> 出口會帶有隱含的名字“default”。

在向具名插槽提供內容的時候,我們可以在一個 <template> 元素上使用 v-slot 指令,並以 v-slot 的參數的形式提供其名稱:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

現在 <template> 元素中的所有內容都將會被傳入相應的插槽。

最終渲染結果如下所示:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

註意 v-slot 只能添加在 <template> 上 (只有一種例外情況),這一點和已經廢棄的 slot attribute 不同。

2、後備內容

有時為一個插槽設置具體的後備 (也就是預設的) 內容是很有用的,它只會在沒有提供內容的時候被渲染。例如在一個 <submit-button> 組件中:

<button type="submit">
  <slot></slot>
</button>

我們可能希望這個 <button> 內絕大多數情況下都渲染文本“Submit”。為了將“Submit”作為後備內容,我們可以將它放在 <slot> 標簽內:

<button type="submit">
  <slot>Submit</slot>
</button>

現在當我在一個父級組件中使用 <submit-button> 並且不提供任何插槽內容時:

<submit-button></submit-button>

後備內容“Submit”將會被渲染:

<button type="submit">
  Submit
</button>

但是如果我們提供內容:

<submit-button>
  Save
</submit-button>

則這個提供的內容將會被渲染從而取代後備內容:

<button type="submit">
  Save
</button>

3、動態插槽名

動態指令參數也可以用在 v-slot 上,來定義動態的插槽名:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

4、具名插槽的縮寫

跟 v-on 和 v-bind 一樣,v-slot 也有縮寫,即把參數之前的所有內容 (v-slot:) 替換為字元 #。例如 v-slot:header 可以被重寫為 #header

<base-layout>
    <template #header>
        <h1>Here might be a page title</h1>
    </template>

    <template #default>
        <p>A paragraph for the main content.</p>
        <p>And another one.</p>
    </template>

    <template #footer>
        <p>Here's some contact info</p>
    </template>
</base-layout>

七、混入

1、基礎

混入 (mixin) 提供了一種非常靈活的方式,來分發 Vue 組件中的可復用功能。一個混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被“混合”進入該組件本身的選項。

例子:

// 定義一個混入對象
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}

// 定義一個使用混入對象的組件
var Component = Vue.extend({
  mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"

2、選項合併

當組件和混入對象含有同名選項時,這些選項將以恰當的方式進行“合併”。

比如,數據對象在內部會進行遞歸合併,併在發生衝突時以組件數據優先。

var mixin = {
  data: function () {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}

new Vue({
  mixins: [mixin],
  data: function () {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created: function () {
    console.log(this.$data)
    // => { message: "goodbye", foo: "abc", bar: "def" }
  }
})

同名鉤子函數將合併為一個數組,因此都將被調用。另外,混入對象的鉤子將在組件自身鉤子之前調用。

var mixin = {
  created: function () {
    console.log('混入對象的鉤子被調用
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 輸入系統 常見的輸入設備有鍵盤、滑鼠、遙控桿、書寫板、觸摸屏等等,用戶通過這些輸入設備與Linux系統進行數據交換。 內核中怎樣表示一個輸入設備 // include/linux/input.h struct input_dev { const char *name; //設備名稱 const ch ...
  • Mac支持 NTFS 系統版本 CPU型號 Ventura 13.2 Apple M1 安裝brew 前往官網查看官網安裝教程,安裝過程中可能存在安裝失敗的問題,基本安裝失敗都是網路的問題。可以嘗試使用知乎大佬金牛肖馬的國內加速安裝腳本。 brew官網 國內加速安裝 安裝macfuse 是安裝mac ...
  • (一)ARP之 數據包接收過程 ​ ​ 先看一下整個數據流的傳輸過程。 首先etherneti_input()函數 從底層網卡驅動接收到原始數據,若是ip包或者ARP包則調用ethernet_input()。 s32_t ethernetif_input(struct netif *netif) { ...
  • 關於LWIP網路協議在嵌入式設備使用越來越廣泛,還是要好好學習一下,之前也看過一些資料,總是學了又忘(可能實踐的太少了吧!!)。所以本文重新整理一下筆記。共同進步! (一)ARP基礎知識 (1)ARP協議的本質: ​ ARP協議的基本功能是使用目標主機的IP地址,查詢其對應的MAC地址,來進行底層鏈 ...
  • 前言 Pod因記憶體不足消失,可能由2種不同的故障導致,其中對故障2的復現、監控比較繁瑣、耗時、棘手; 故障1:Pod自身記憶體不足 Pod中的運行進程占用空間超出了Pod設置的Limit限制,導致該Pod中進程被Pod內的OS內核Kill掉; 此時Pod的Status為OOMKilled,Pod的OO ...
  • 一、IDEA連接本地MySQL 點擊IDEA右側欄Database 在Data Sources中選擇MySQL (host 欄localhost port 欄 3306 user欄 root【資料庫用戶名】 password欄 root【資料庫密碼】 database欄 可填可不填) 填完後先點擊左 ...
  • Redis事務定義 Redis 事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。 Redis 事務的主要作用就是串聯多個命令防止別的命令插隊。 Multi、Exec、discard Redis 事務中有 Multi、Ex ...
  • 1. 需求:我們現在需要寫一個 foo 函數,這個函數返迴首次調用時的 Date 對象,註意是首次。 使用場景:當我們每次都需要進行條件判斷,其實只需要判斷一次,接下來的使用方式都不會發生改變的時候,想想是否可以考慮使用惰性函數。 惰性函數:顧名思義,有點懶惰,懶到事件只處理一次,當然不是值整個函數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...