a. 父 -> 子(父組件傳遞數據給子組件)javascript
使用 props,具體查看文檔 - 使用 Prop 傳遞數據(cn.vuejs.org/v2/guide/co…css
b. 父 -> 子(在父組件上調用子組件內的方法)html
使用 ref,具體查看文檔 - 子組件索引(cn.vuejs.org/v2/guide/co…前端
<!--父組件 template--> <div id="parent"> <!--子組件--> <user-profile ref="profile"></user-profile> </div>
// 父組件 script this.$refs.profile.someMethod();
注意:若是在子組件上設置 ref 屬性,則能夠經過 this.$refs 獲取到該子組件對象,若是在普通的 html 標籤上設置 ref 屬性,則獲取到的是 Dom 節點。vue
c. 子 -> 父(在父組件上獲取子組件內的數據)java
同上,也是利用 refwebpack
// 父組件 script let childData = this.$refs.profile.someData;
d. 子 -> 父(子組件內觸發事件,父組件監聽事件)web
父組件能夠在使用子組件的地方直接用
v-on
來監聽子組件觸發的事件,具體查看文檔 - 使用 v-on 綁定自定義事件(cn.vuejs.org/v2/guide/co…ajax<!--父組件 template--> <div id="parent"> <!--子組件--> <user-profile @childTrigger="parentHandle"></user-profile> </div>
// 父組件 script methods: { parentHandle(params){ // 這個方法在子組件 emit childTrigger 事件後會執行 // params 爲子組件裏觸發事件時傳的參數 } }
// 子組件 user-profile script this.$emit('childTrigger', params);
e. 子 -> 父(子組件傳值,父組件裏使用,具體實現見 03)vue-router
01總結:
應用場景示例:在父組件上打開側邊欄子組件,能夠傳 prop visible(true
)來控制側邊欄打開;側邊欄內部有關閉按鈕,就在點擊關閉按鈕後觸發一個事件,父組件監聽事件執行方法將 data visible 改成false
。
PS:父組件傳值到子組件,傳的值是Object
類型,子組件使用v-model
能夠修改該值(將某個表單元素的v-model
設爲該值),父組件可直接獲取到改變後的值。
有時候會用到一些工具類函數,但願能夠全局調用,而不是侷限於某個組件中。
Step 1:
在 項目根目錄/static/js/
目錄下新建一個 util.js
文件,將經常使用的工具函數寫在這裏面。
Step 2:
在 index.html
裏面引入 util.js
,就能夠在 .vue
文件裏使用那些方法了,以下:
<body>
<div id="app"></div> <!-- 引入經常使用 js 方法 --> <script type="text/javascript" src="/static/js/util.js"></script> <!-- built files will be auto injected --> </body>
02總結:
使用這個方法可使得一些使用頻率高的函數能夠在全部.vue
文件中被調用,笨拙而又簡單。
之前看文檔時一直不理解如何使用 slot,如今用多了 elementui 的組件以後,就漸漸發現了它的實用性。
簡單來講,使用 slot 可使咱們作到:在父組件裏使用子組件時,在子組件裏插入一些自定義的內容(html 代碼啥的),具體查看文檔:cn.vuejs.org/v2/guide/co…
更神奇的功能是 做用域插槽,可讓咱們在父組件裏使用子組件時,獲取子組件傳來的數據,具體查看文檔:cn.vuejs.org/v2/guide/co…
簡單應用示例:
<!-- a-button 子組件 --> <button type="button" class="a-button" @click="$emit('btn-click')"><slot></slot></button> <!-- 這裏監聽了 button 的 click 事件,而後又觸發了 btn-click 事件 -->
<!-- 父組件 --> <a-button @btn-click="handleClick">這裏寫的東西會覆蓋子組件裏的 slot 標籤所在的位置</a-button> <!-- 這裏監聽了子元素觸發的 btn-click 事件,而後執行 handleClick 函數 -->
渲染結果:
<button type="button" class="a-button">這裏寫的東西會覆蓋子組件裏的 slot 標籤所在的位置</button>
能夠應用簡單的 slot 來達到爲不一樣的按鈕填充文字的目的:
<a-button @click="handleClick">詳情</a-button> <a-button @click="handleClick">搜索</a-button> <!-- 渲染結果 --> <button type="button" class="a-button">詳情</button> <button type="button" class="a-button">搜索</button>
做用域插槽示例:
<!-- 子組件 --> <div class="child"> <!-- slot 這個位置會在子組件被使用時被父組件傳來的 html 代碼覆蓋 --> <!-- slot 上的 text/child 就至關於傳給父組件的 props (假設 name 爲子組件的 data,name: someChild) --> <slot text="hello from child" :child="name"></slot> </div>
在父級中,具備特殊屬性 scope
的 <template>
元素,表示它是做用域插槽的模板。scope
的值對應一個臨時變量名,此變量接收從子組件中傳遞的 prop
對象:
<!-- 父組件 --> <div class="parent"> <child> <template scope="props"> <span>hello from parent</span> <span>{{ props.text }}</span> <span>{{ props.child }}</span> </template> </child> </div>
渲染結果:
<div class="parent"> <div class="child"> <span>hello from parent</span> <span>hello from child</span> <span>someChild</span> </div> </div>
03總結:
應用場景示例:elementui 的 button 組件中有簡單插槽的使用,table 組件則使用到了 做用域插槽。
<!-- button 組件 --> <el-button>默認按鈕</el-button> <el-button type="primary">主要按鈕</el-button> <el-button type="text">文字按鈕</el-button> <!-- table 組件 --> <el-table :data="tableData"> <el-table-column prop="zip" label="郵編" width="120"> </el-table-column> <el-table-column fixed="right" label="操做" width="100"> <template scope="scope"> <el-button <!-- 能夠經過 scope.$index 獲取到當前行的索引 --> @click.native.prevent="deleteRow(scope.$index)"> 移除 </el-button> </template> </el-table-column> </el-table>
vue-router 的使用,簡單來講就是經過配置,實如今不一樣的 url 路徑下,頁面渲染不一樣的組件。具體查看文檔:vue-router 2。
使用示例
一級路由:
<!-- App.vue --> <!-- 該組件爲最高級父組件,使用 router-view 來根據路徑肯定要顯示的子組件 --> <template> <div id="app"> <!-- router-view 位置用來顯示組件,如顯示下面的 index.vue --> <router-view></router-view> </div> </template>
二級路由(路由可嵌套):
<!-- page/index.vue --> <!-- 該組件包含一個頂部欄和側邊菜單欄,內容區使用 router-view 來根據 url 路徑顯示子組件 --> <template> <div class="index"> <!-- 頂部導航條 --> <header class="main-header"> ... </header> <!-- /頂部導航條 --> <!-- 側邊導航欄 --> <aside class="main-sidebar sidebar-gradient"> ... </aside> <!-- /側邊導航欄 --> <!-- 根據頁面一級菜單的點擊而進行切換的內容區 --> <transition name="fade"> <!-- router-view 位置用來顯示組件 --> <router-view></router-view> </transition> <!-- /內容區 --> </div> </template>
router 配置:
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; // 引入組件 import index from 'page/index'; // 該組件包含一個頂部欄和側邊菜單欄,內容區使用 router-view 來根據 url 路徑顯示子組件 import notFoundComponent from 'page/404'; // 該組件爲 404 頁面,當你路由使用 history 模式時須要用到 import monitorIndex from 'page/monitor/index'; // 該組件爲一個監控頁面,用於顯示在 page/index.vue 頁面上的 router-view 處(即頁面的內容區域) Vue.use(Router); // 定義 scrollBehavior 方法 const scrollBehavior = (to, from, savedPosition) => { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } } export default new Router({ mode: 'history', // mode 默認 hash 值,可是 hash (url中包含 # 符號)不太好看也不符合咱們通常的網址瀏覽習慣 // 當你使用 history 模式時,URL 就像正常的 URL,例如 http://yoursite.com/user/id,也好看! linkActiveClass: 'active', // 默認值: 'router-link-active',就是當前組件被激活,相應路由會自動添加類 'router-link-active',這裏是爲了全局設置激活類名,若是不設置,直接用默認的也是能夠的 // 如:使用 router-link 組件來導航,經過傳入 `to` 屬性指定連接 // <router-link to="/foo">Go to Foo</router-link> // <router-link> 默認會被渲染成一個 `<a>` 標籤,'/foo' 路由下的組件顯示時,該 a 標籤上會自動添加類 'active' scrollBehavior: scrollBehavior, // 經過這個屬性(是個函數),可讓應用像瀏覽器的原生表現那樣,在按下 後退/前進 按鈕時,簡單地讓頁面滾動到頂部或原來的位置,若是不設置,則組件切換時滾動條位置不變 routes: [ { // 一級路由 path: '/', component: index, children: [ // 二級路由 // -----------默認首頁------------- // 當 / 匹配成功,monitorIndex 會被渲染在 index 的 <router-view> 中 { path: '', component: monitorIndex, alias: 'index.html' }, // 這裏的 alias 'index.html' 爲當前頁面的別名 // http://localhost:8080/index.html 等同於 http://localhost:8080/ // -----------監控中心------------- { // 當 /monitor 匹配成功, // monitorIndex 會被渲染在 index 的 <router-view> 中 path: 'monitor', name: '監控中心', component: monitorIndex } ] }, // 同一個路徑能夠匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高 // 所以下面的路由配置爲備用,若是某個路徑未被配置顯示相應的組件,則顯示 404 頁面 { path: '*', component: notFoundComponent } ] });
引入 router 配置:
// main.js import Vue from 'vue'; // 引入 element ui 組件 import { Dropdown, DropdownMenu ...} from 'element-ui'; // 引入 App.vue import App from './App'; // 引入 router 配置 import router from './router'; // 默認會找到 router 文件夾下的 index.js 文件 // 引入項目圖標的 sprite css,能夠簡單的經過這種方式引入 css 文件 import './assets/css/sprite.css' // 使用 element ui 組件 Vue.use(Dropdown) Vue.use(DropdownMenu) ... new Vue({ el: '#app', router, // 使用 router 配置 template: '<App/>', components: { App }, });
04總結:
關於 vue-router 的使用,看文檔通常都能解決你的疑問,vue-router 2。
其餘參考文章:Vue.js系列之vue-router(中)(4)
PS:使用 history 模式的話,還須要 後臺配置 支持。由於咱們的應用是個單頁客戶端應用,若是後臺沒有正確的配置,當用戶在瀏覽器直接訪問http://oursite.com/user/id
就會返回 404(由於的確找不到該頁面),這就很差看了。而且在後臺配置後,還須要前端來提供 404 頁面,我上面的示例代碼中有提到,可供參考。
使用 Vue 開發單頁應用時,先後端分離開發,進度不一。所以前端有時候就須要本身模擬接口的 json 文件,而後直接使用異步請求方法(如 ajax) 去獲取數據,渲染頁面,測試代碼等。
Step 1:
在 項目根目錄/static/api/
目錄下新建一個 test.json
文件,寫入模擬的接口數據:
{ "status": true, "data": { ... } }
Step 2:
在 .vue
組件文件裏任意須要請求數據的方法裏(如 created
鉤子,或者某個 methods 方法裏)編寫相關代碼:
let vm = this; // ajax 請求數據 $.ajax({ type: 'GET', url: 'static/api/test.json', data: '', beforeSend: function() { // 顯示 Loading vm.loading = true; }, complete: function() { // 隱藏 Loading vm.loading = false; }, success: function(data) { // 處理返回數據 ... }, error: function() { // 數據請求失敗,給用戶適當的反饋信息 ... }, dataType: 'json' });
05總結:
在後端還沒有提供接口時,我都是用這個方法來測試前端獲取數據和處理數據的代碼是否正確。
咱們能夠爲組件的 props 指定驗證規格。若是傳入的數據不符合規格,Vue 會發出警告。當組件給其餘人使用時,這頗有用。
示例以下:
props: {
// 基礎類型檢測 (`null` 意思是任何類型均可以) propA: Number, // 多種類型 propB: [String, Number], // 必傳且是字符串 propC: { type: String, required: true }, // 數字,有默認值 propD: { type: Number, default: 100 }, // 數組/對象的默認值應當由一個工廠函數返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定義驗證函數 propF: { validator: function (value) { return value > 10 } } }
愚蠢的我每次想要傳 Number
或者 Boolean
類型的值到子組件時,都在父組件裏定義好值,而後再綁定到子組件上:
// 這樣會報錯,由於 show type 爲 Boolean,rows type 爲 Number // 默認狀況下直接傳值,子組件接收到的都是 String 類型 // template <child show="true" rows="6"></child>
// 因而我這樣作: // template <child :show="show" :rows="rows"></child> // script show: true, rows: 6
// 實際上能夠直接這樣作: // template <child :show="true" :rows="6"></child> // 官網如是說:若是想傳遞一個實際的 number,須要使用 v-bind ,從而讓它的值被看成 JavaScript 表達式計算。
小技巧:當某個 prop 類型爲 Boolean 時,能夠直接把該 prop 的名稱寫在組件上,默認會傳 true,不寫的話默認爲 false。好比
<child show :rows="6"></child>
這麼寫,子組件內部就能收到 show 爲 true。
有些人會問如何在項目裏使用
autoprefixer
插件,事實上使用vue-cli
的webpack
模板生成的項目裏已經帶有autoprefixer
的使用了,以下圖:
autoprefixer
對項目進行
npm run build
操做後,發現生成的文件超大(比想象中的大),尤爲是那些.map
文件,不過,咱們能夠經過配置選擇不生成該類文件。
// 項目根目錄/config/index.js var path = require('path') module.exports = { build: { ... productionSourceMap: false, // 將該值設爲 false,就不會生成 .map 文件了 // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin productionGzip: false, productionGzipExtensions: ['js', 'css'], ... }, dev: { ... } }
原文連接:https://juejin.im/post/58f37bfe5c497d006c90ca28