例如在組件建立時須要獲取一次數據列表,而後監聽數據的變化,根據數據改變從新獲取列表。一般這麼寫:html
created(){ this.fetchPostList() }, watch: { changeValue(){ this.fetchPostList() } }
可是上面的這種寫法咱們能夠精簡寫成以下:vue
watch: { changeValue:{ handler: 'fetchPostList', immediate: true } }
聲明
immediate:true
, 表示建立的時候當即執行一次。
通常狀況下,組件寫法以下:webpack
import BaseButton from './baseButton' import BaseIcon from './baseIcon' import BaseInput from './baseInput' export default { components: { BaseButton, BaseIcon, BaseInput } } <BaseInput v-model="searchText" @keydown.enter="search" /> <BaseButton @click="search"> <BaseIcon name="search"/></BaseButton>
通常步驟有三步:web
這是最多見和通用的寫法。可是若是組件過多,則要引入屢次,註冊屢次。vue-router
咱們能夠藉助一下webpack,使用 require.context() 方法來建立本身的(模塊)上下文,從而實現自動動態require組件。vuex
思路是:在src文件夾下面main.js中,藉助webpack動態地將須要的基礎組件通通打包進來。異步
代碼以下:函數
一些方法解釋: upperFirst 、 camelCase 、 require.context()
import Vue from 'vue' import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase' // Require in a base component context const requireComponent = require.context( ‘./components', false, /base-[\w-]+\.vue$/ ) requireComponent.keys().forEach(fileName => { // Get component config const componentConfig = requireComponent(fileName) // Get PascalCase name of component const componentName = upperFirst( camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')) ) // Register component globally Vue.component(componentName, componentConfig.default || componentConfig) })
這樣咱們引入組件只須要第三步就能夠了:post
<BaseInput v-model="searchText" @keydown.enter="search" /> <BaseButton @click="search"> <BaseIcon name="search" /></BaseButton>
對於vuex,咱們輸出store寫法以下:fetch
import auth from './modules/auth' import posts from './modules/posts' import comments from './modules/comments' ... export default new Vuex.Store({ modules: { auth, posts, comments, ... } })
要引入不少modules,而後再註冊到Vuex.Store中。。
精簡的作法也是運用 require.context()讀取文件,代碼以下:
import camelCase from 'lodash/camelCase' const requireModule = require.context('.', false, /\.js$/) const modules = {} requireModule.keys().forEach(fileName => { // Don't register this file as a Vuex module if (fileName === './index.js') return const moduleName = camelCase( fileName.replace(/(\.\/|\.js)/g, '') ) modules[moduleName] = { namespaced: true, ...requireModule(fileName), } }) export default modules
這樣咱們只需以下代碼就能夠了:
import modules from './modules' export default new Vuex.Store({ modules })
在平時的demo中,可能不會碰見這個需求。當頁面不少,組件不少的時候,SPA頁面在首次加載的時候,就會變的很慢。這是由於vue首次加載的時候把可能一開始看不見的組件也一次加載了,這個時候就須要對頁面進行優化,就須要異步組件了。
在路由index.js裏(路徑: src/router/index.js
),經過require方式或者import()方式動態加載組件。像下面這樣:
{ path: '/home', name: 'home', component:require('@views/home').default }
或者
{ path: '/home', name: 'home', component:() => import('@views/home') }
router :key
進行組件刷新首先默認使用的是Vue-router來實現路由的控制。假設如今在寫一個網站,需求是從
/post/a
跳轉到/post/b
。而後咱們就會發現,頁面跳轉後數據居然沒更新?!緣由是vue-router 「智能地」 發現這是同一個組件,而後它就決定要複用這個組件,因此在created函數裏寫的方法所有沒有執行。
一般的解決方案是監聽$route的變化來初始化數據,以下:
data() { return { loading: false, error: null, post: null } }, watch: { '$route': { handler: 'resetData', immediate: true } }, methods: { resetData() { this.loading = false this.error = null this.post = null this.getPost(this.$route.params.id) }, getPost(id){} }
問題是解決了,可是這樣的處理方式不夠優雅。咱們但願代碼這樣寫:
data() { return { loading: false, error: null, post: null } }, created () { this.getPost(this.$route.params.id) }, methods () { getPost(postId) { ... } }
如何達到這樣的效果:給router-view添加一個惟一的key
,這樣只要url
變化了,就必定會從新建立這個組件。就避免了vue-rouer由於複用組件致使created函數中的方法不執行的問題。
<router-view :key="$route.fullpath"></router-view>
注: 這個通常應用在子路由裏面,這樣才能夠避免大量重繪,假設App.vue根目錄添加這個屬性,那麼每次點擊改變地址都會重繪!