Vue 的小奇技

1.監聽第三方組件的生命週期鉤子

通過使用 @hook: 前綴監聽生命週期中的鉤子,並指定回調函數。
舉個例子,如果你想要在第三方組件 v-runtime-template 渲染時做一些事情,那麼你可以監聽它的生命週期中的 updated 鉤子:

<v-runtime-template @hook:updated="doSomething" :template="template" />

2.用Object.freeze 方法阻止vue的data中數據響應

比如我們請求的數據是一個很大的數據列表。如地圖的標記點 markers 列表數據,這就是一個擁有很多對象的大型數組,我們不會對這些數據進行操作,其實可以理解成這是一個常量。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

如果你確實有需要去修改請求得到的列表數據,那麼你仍然可以通過創建一個新的數組來實現。

this.users = Object.freeze([...this.users, user]);

3.Vue.js 2.6.0 中的新指令 v-slot

(1)作用域插槽
原方法:

<template>
    <List :items="items">
        <template slot-scope="{ filteredItems }">
            <p v-for="item in filteredItems" :key="item">{{ item }}</p>
        </template>
    </List>
</template>

然而,我們可以直接在組件標籤上使用新指令v-slot,避免了額外的嵌套:
記住 v-slot指令只能用在組件或 template標籤上,而不能使用在原生 html 標籤上

<template>
    <List v-slot="{ filteredItems }" :items="items">
        <p v-for="item in filteredItems" :key="item">{{ item }}</p>
    </List>
</template>

(2)v-slot指令也提供了一個綁定slotscope-slot 指令的方式,但是需要使用一個 : 來分割它們
原方法:

<template>
  <Promised :promise="usersPromise">
    <p slot="pending">Loading...</p>

    <ul slot-scope="users">
      <li v-for="user in users">{{ user.name }}</li>
    </ul>

    <p slot="rejected" slot-scope="error">Error: {{ error.message }}</p>
  </Promised>
</template>

v-slot指令重寫如下:

<template>
    <Promised :promise="usersPromise">
        <template v-slot:pending>
            <p>Loading...</p>
        </template>

        <template v-slot="users">
            <ul>
                <li v-for="user in users">{{ user.name }}</li>
            </ul>
        </template>

        <template v-slot:rejected="error">
            <p>Error: {{ error.message }}</p>
        </template>
    </Promised>
</template>

v-slot以符號 # 作爲其指令的簡寫模式,v-slot指令默認應該簡寫爲#default

<template>
    <Promised :promise="usersPromise">
        <template #pending>
            <p>Loading...</p>
        </template>

        <template #default="users">
            <ul>
                <li v-for="user in users">{{ user.name }}</li>
            </ul>
        </template>

        <template #rejected="error">
            <p>Error: {{ error.message }}</p>
        </template>
    </Promised>
</template>

4.$attrs/$listeners使用

假設我們有一個基礎組件,比如說 BaseList,然後你想要在此基礎上創建一個有額外功能的相類似的組件,比如說 SortableList。我將其稱作爲自適應組件(或者是代理組件、包裝組件)。
注意如果父組件是通過rander出來的無效,爲啥?

//在父組件當中,最外層組件
<template>
    <div>
        <Child1 :child1Info="child1" :child2Info="child2" v-on:test1="onTest1" v-on:test2="onTest2">
        </Child1>
    </div>
</template>
<script>
import Child1 from './child1';
export default {
    data() {
        return {
            child1:"hahha",
            child2:"asdsdasd"
        };
    },
    components: { Child1 },
    methods: {
        onTest1(msg) {
            console.log('test1 running...',msg);
        },
        onTest2(msg) {
            console.log('test2 running',msg);
        }
    }
};
</script>

inheritAttrs屬性默認是true 就是$prop和原生屬性(style ,value,placeholder)都會傳遞下去設置爲flase原生屬性除了class都不會傳下去

//在子組件中
<template>
    <div class="child-1">
        <p>在子組件當中:</p>
        <p>props-child1Info: {{child1Info}}</p>
        <p>$attrs: {{$attrs}}</p>
        <hr>
        <!-- Child2組件中能直接觸發test的原因在於 B組件調用C組件時 使用 v-on 綁定了$listeners 屬性 -->
        <!-- 通過v-bind 綁定$attrs屬性,Child2組件可以直接獲取到A組件中傳遞下來的props(除了child1組件中props聲明的) -->
        <Child2 v-bind="$attrs" v-on="$listeners" inheritAttrs="false"></Child2>
    </div>
</template>
<script>
import Child2 from './child2';
export default {
    props: ['child1Info'], //$attr會剔除child1Info屬性
    data() {
        return {};
    },
    components: { Child2 },
    mounted() {
        this.$emit('test1','嘻嘻');
    }
};
</script>


//在孫子組件當中:


<template>
    <div class="child-2">
        <p>在最裏層組件當中child2:</p>
        <p>props-child2Info: {{child2Info}}</p>
        <p> $attrs 的值: {{$attrs}}</p>
        <hr>
    </div>
</template>
<script>
export default {
    props: ['child2Info'],
    data() {
        return {};
    },
    mounted() {
        this.$emit('test2','哈哈');
    }
};
</script>

5.動態組件 & is 的用法

Vue 文檔中關於動態組件部分的描述大概就是:使用保留的 元素配合動態綁定的 is 屬性就可以在同一個掛載點切換不同的組件
這裏面動態的關鍵在於 is 屬性,而不在於 ,換句話說,就是隨便你用什麼標籤,只要有 is 屬性,它就算是動態組件, 當然你也可以靜態地給 is 賦值一個字符串,不過這樣它就只能表示某一個組件,失去了動態的意義了。
文檔中有個render的列子

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // tag name
      this.$slots.default // array of children
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

其實就單單這個例子來說,也可以使用 is + template 的方法,比 render function 還要簡潔直觀:

<script type="text/x-template" id="anchored-heading-template">
  <component :is="'h' + level">
    <slot></slot>
  </component>
</script>

6.將組件插入body中

mounted放法中寫

this.$nextTick(() => {
      const body = document.querySelector("body");
      if (body.append) {
        body.append(this.$el);
      } else {
        body.appendChild(this.$el);
      }
    });

7. 修改scoped樣式

// 普通樣式中
  .a >>> .b { /* ... */ }
  
// sass 、less
.a{
  /deep/ .b{
    /* ... */
  }
}

8.定時器清除

一般我們都是在beforeDestroy()生命週期內清除定時器,但是下面這個方法更加簡潔

const timer = setInterval(() =>{                    
    // 某些定時器操作                
}, 500);            
// 通過$once來監聽定時器,在beforeDestroy鉤子可以被清除。
this.$once('hook:beforeDestroy', () => {            
    clearInterval(timer);                                    
})

類似於其他需要在當前頁面使用,離開需要銷燬的組件(例如一些第三方庫的picker組件等等),都可以使用此方式來解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章