主頁 > 企業開發 > Vue的基礎知識(三)

Vue的基礎知識(三)

2023-02-27 07:58:28 企業開發

本章將繼續和大家分享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=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/js/lib/vue.js"></script>
    <script src=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/js/lib/axios.js"></script>
    <script src=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/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=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/js/lib/require.js"></script>
    <script src=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/js/common/require_config.js"></script>
    <script src=https://www.cnblogs.com/xyh9039/archive/2023/02/26/"/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('混入物件的鉤子被呼叫')
  }
}

new Vue({
  mixins: [mixin],
  created: function () {
    console.log('組件鉤子被呼叫')
  }
})

// => "混入物件的鉤子被呼叫"
// => "組件鉤子被呼叫"

值為物件的選項,例如 methodscomponents 和 directives,將被合并為同一個物件,兩個物件鍵名沖突時,取組件物件的鍵值對,

var mixin = {
  methods: {
    foo: function () {
      console.log('foo')
    },
    conflicting: function () {
      console.log('from mixin')
    }
  }
}

var vm = new Vue({
  mixins: [mixin],
  methods: {
    bar: function () {
      console.log('bar')
    },
    conflicting: function () {
      console.log('from self')
    }
  }
})

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

注意:Vue.extend() 也使用同樣的策略進行合并,

3、全域混入

混入也可以進行全域注冊,使用時格外小心!一旦使用全域混入,它將影響每一個之后創建的 Vue 實體,使用恰當時,這可以用來為自定義選項注入處理邏輯,

// 為自定義的選項 'myOption' 注入一個處理器,
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

new Vue({
  myOption: 'hello!'
})
// => "hello!"

請謹慎使用全域混入,因為它會影響每個單獨創建的 Vue 實體 (包括第三方組件),大多數情況下,只應當應用于自定義選項,就像上面示例一樣,推薦將其作為插件發布,以避免重復應用混入,

 

Demo原始碼:

鏈接:https://pan.baidu.com/s/1jc5SGf3_8qb6pZT4T-5mxA 
提取碼:broa 

此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/17139196.html

著作權宣告:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/545150.html

標籤:其他

上一篇:ES6中的class物件和它的家人們

下一篇:js-惰性函式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more