vue實戰項目:項目技巧總結(彙總成一篇了)

1、建立項目及配置

1.1 vue cli2 建立項目

vue init webpack project
複製代碼
npm install
複製代碼
npm run dev
複製代碼

1.2 vue cli3 建立項目

vue create project
複製代碼

選擇配置,看我的項目需求javascript

TypeScript 支持使用 TypeScript 書寫源碼
 Progressive Web App (PWA) Support PWA 支持。
 Router 支持 vue-router 。
 Vuex 支持 vuex 。
 CSS Pre-processors 支持 CSS 預處理器。
 Linter / Formatter 支持代碼風格檢查和格式化。
 Unit Testing 支持單元測試。
 E2E Testing 支持 E2E 測試。
複製代碼

進入到項目根目錄css

cd  project
複製代碼

啓動項目html

npm run serve
複製代碼

2、安裝 element-UI

npm i element-ui -S
複製代碼

2.1main.js 引入

2.1.1 全局引入
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(Element)
複製代碼
2.1.2 按需引入

首先,安裝 babel-plugin-componentvue

npm install babel-plugin-component -D
複製代碼

而後,將 .babelrc 修改成:java

{
 "presets": [
  ["es2015", {
   "modules": false
  }]
 ],
 "plugins": [
  [
   "component",
   {
    "libraryName": "element-ui",
    "styleLibraryName": "theme-chalk"
   }
  ]
 ]
}
複製代碼

接下來,若是你只但願引入部分組件,好比 ButtonSelect,那麼須要在 main.js 中寫入如下內容:node

import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';
 Vue.component(Button.name, Button); Vue.component(Select.name, Select);  複製代碼

或寫爲webpack

- Vue.use(Button)
- Vue.use(Select)
複製代碼

3、安裝 vuex

npm i vuex -s
複製代碼
3.1 /src/store 下面的 index.js 中
import Vue from 'vue'
import Vuex from 'vuex'
 //掛載 Vuex Vue.use(Vuex)  //建立 VueX 對象 const store = new Vuex.Store({ state:{name: 'helloVueX', }, mutations:{}, actions:{}, modules:{} })  export default store  複製代碼
3.2 main.js 引入

store 掛載到當前項目的 Vue 實例當中去ios

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
 Vue.config.productionTip = false  new Vue({ el: '#app', router, store, //store:store 和 router 同樣,將咱們建立的 Vuex 實例掛載到這個 vue 實例中 render: h => h(App) }) 複製代碼
3.3 在組件中使用 Vuex
<template>
    <div id='app'>
      name:
      <h1>{{ $store.state.name }}</h1>
    </div>
</template>
 methods:{ add(){ console.log(this.\$store.state.name) } }, 複製代碼

更具體的學習文檔參考個人網站: 學習文檔git

4、配置scss環境

4.1.首先安裝依賴
npm install node-sass sass-loader --save-dev 
複製代碼
4.2.找到 build 中 webpack.base.conf.js,在 rules 中添加 scss 規則
{
  test: /\.scss\$/,
  loaders: ['style', 'css', 'sass']
} 
複製代碼
4.3.在 vue 文件中使用

github

<style lang='scss'> 複製代碼</style> 複製代碼

4.4 在 vue 項目全局中引入 scss

1.全局引用時須要安裝 sass-resources-loader
npm install sass-resources-loader --save-dev 
複製代碼
2.修改 build 中的 utils.js

scss: generateLoaders('sass')

修改成
scss: generateLoaders('sass').concat({
 loader: 'sass-resources-loader',
 options: {
  //你本身的 scss 全局文件的路徑
  resources: path.resolve(\_\ _dirname, '../src/style/common.scss')
 }
})
複製代碼

若是上面的不能正常編譯

//配置 sass 編譯路徑
 function generateSassResourceLoader() { let loaders = [ cssLoader, 'sass-loader', { loader: 'sass-resources-loader', options: { // 多個文件時用數組的形式傳入,單個文件時能夠直接使用 path.resolve(__dirname, '../static/style/common.scss' resources: path.resolve(__dirname, '../src/style/common.scss') } } ]; if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }); } else { return ['vue-style-loader'].concat(loaders); } } 複製代碼
在 cssLoaders 裏面引入
sass:generateSassResourceLoader(),//新加的
scss:generateSassResourceLoader(),//新加的
複製代碼

4.5 引入全局的 sass

npm install --s node-sass sass-loader
複製代碼

1.首先你須要

npm install --s sass-resources-loader 
複製代碼

2.在 build 目錄下找到 utils.js 文件

Module build failed: TypeError: this.getResolve is not a function at Object.loader 複製代碼

安裝 node-sass 運行報錯 vue 安裝 node-sass 編譯報錯 安裝node-scss報錯 安裝 node-scss 報錯

在搭建 vue 腳手架 或者是在 vue 項目中,想使用 sass 的功能,

npm install node-sass --save-dev //安裝 node-sass
npm install sass-loader --save-dev //安裝 sass-loader
npm install style-loader --save-dev //安裝 style-loader
複製代碼

這是由於當前 sass 的版本過高,webpack 編譯時出現了錯誤,這個時候只須要換成低版本的就行,下面說一下修改方法,很簡單,以下,找到 package.json 文件,裏面的 "sass-loader"的版本更換掉 就好了。

"sass-loader": "^8.0.0",更換成了 "sass-loader": "^7.3.1",
複製代碼

也能夠先卸載當前版本,而後安裝指定的版本

卸載當前版本
npm uninstall sass-loader
複製代碼
安裝
npm install sass-loader@7.3.1 --save-dev
複製代碼

5、配置less環境

安裝 lessless-loader
npm install less less-loader --save
複製代碼

修改 webpack.base.config.js 文件,配置 loader 加載依賴,讓其支持外部的 less,在原來的代碼上添加

// 此種方法在控制檯中標籤樣式顯示的是style標籤樣式
{
 test: /\.less$/,
 loader: "style-loader!css-loader!less-loader",
}
複製代碼
// 能夠在控制檯中看到當前標籤樣式來自於哪一個less文件
{
 test: /\.less$/,
 loader: "style-loader!css-loader!less-loader",
 options: {
  sourceMap: true
 }
}
複製代碼

在 vue 文件中的 style 標籤中添加 lang="less"便可在標籤中使用 less,或者外部引入 less

參考文檔

6、引入font-awesome

npm install font-awesome --save
複製代碼

而後在 main.js 引入 font-awesome/css/font-awesome.min.css 便可。

七、vue 配置網站的 ico

7.1方式一:
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
複製代碼
7.2 方式二
webpack.dev.conf.js
new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'index.html',
  favicon: 'favicon.ico', // 新增
  inject: true
 }),
 webpack.prod.conf.js new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency', favicon: 'favicon.ico' // 新增 }), 複製代碼

8、引入自定義公共樣式

router/index.js 裏面引入公共樣式

import 'bootstrap/dist/css/bootstrap.css' //引入 bootstrap
import 'bootstrap-vue/dist/bootstrap-vue.css'
import '@/common/common.css'
import '@/common/index.css'
複製代碼

9、路由按需加載

const port = () => import('@/pages/port') //入口頁面、
複製代碼
const router = new Router({
  // mode: 'history',
  routes: [
    {
      path: '/',
      name: 'port',
      component: resolve => require.ensure([], () => resolve(require('@/pages/port')), 'port'),
    }]
})
複製代碼

參考文檔

10、全局自定義方法

main.js 裏面掛載方法到 vue.prototype
Vue.prototype.isMobile = function() {
 let flag = navigator.userAgent.match(
  /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
 )
 return flag;
}
複製代碼
組件裏面使用
mounted: function() {
  this.isMobile();
}
複製代碼

11、引入接口文件暴露到全局

11.1 在 main.js 裏面引入接口暴露到全局'
// 接口暴露在全局
import { server } from './config/api'
Vue.prototype.\$server = server;
複製代碼
//api.js
 export const server = { getContentMenu: (paramObj)=>fetch('/content/menu',paramObj),//內容詳情查詢 getContentListPort: (paramObj)=>fetch('/content/list/'+paramObj),//入口頁面接口 getContentList:(paramObj)=>fetch('/content/list/'+paramObj),//內容詳情查詢 getPageviews:(paramObj)=>fetch('/webpage/1/view',paramObj)//流量統計接口 }  組件裏面使用: ```js methods: { getPageviews() { var that = this; let params = { pageId: that.pageId, pageUrl: that.pageUrl, }; that.\$server.getPageviews(params).then(response => {}) } } 複製代碼
11.2 axios 方法封裝,整個 api.js
import axios from 'axios';
 axios.defaults.timeout = 5000; axios.defaults.baseURL =''; //填寫域名  //http request 攔截器 axios.interceptors.request.use( config => { config.data = JSON.stringify(config.data); config.headers = { 'Content-Type':'application/x-www-form-urlencoded' } return config; }, error => { return Promise.reject(err); } );  //響應攔截器即異常處理 axios.interceptors.response.use(response => { return response }, err => { if (err && err.response) { switch (err.response.status) { case 400: console.log('錯誤請求') break; case 401: console.log('未受權,請從新登陸') break; case 403: console.log('拒絕訪問') break; case 404: console.log('請求錯誤,未找到該資源') break; case 405: console.log('請求方法未容許') break; case 408: console.log('請求超時') break; case 500: console.log('服務器端出錯') break; case 501: console.log('網絡未實現') break; case 502: console.log('網絡錯誤') break; case 503: console.log('服務不可用') break; case 504: console.log('網絡超時') break; case 505: console.log('http版本不支持該請求') break; default: console.log(`鏈接錯誤${err.response.status}`) } } else { console.log('鏈接到服務器失敗') } return Promise.resolve(err.response) })  /** * 封裝get方法 * @param url * @param data * @returns {Promise} */  export function fetch(url,params={}){ return new Promise((resolve,reject) => { axios.get(url,{ params:params }) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) }  /** * 封裝post請求 * @param url * @param data * @returns {Promise} */  export function post(url,data = {}){ return new Promise((resolve,reject) => { axios.post(url,data) .then(response => { resolve(response.data); },err => { reject(err) }) }) }  /** * 官網接口請求封裝 * @param url * @param data * @returns {Promise} */  export const server = { getContentMenu: (paramObj)=>fetch('/content/menu',paramObj),//內容詳情查詢 getContentListPort: (paramObj)=>fetch('/content/list/'+paramObj),//入口頁面接口 getContentList:(paramObj)=>fetch('/content/list/'+paramObj),//內容詳情查詢 getPageviews:(paramObj)=>fetch('/webpage/1/view',paramObj)//流量統計接口 }  複製代碼

12、provide /inject 完美解決不跳轉不閃動頁面刷新

原理:此方法使用的是 v-if 來控制 router-view 的顯示或隱藏,v-if 從 false 變爲 true 時,vue 會從新渲染 router-view 區域,因此當參數變化時,只需讓 v-if 從 true => false => true,就能實現頁面刷新。

12.1 找到route-view

//App.vue <template> <div id="app"> <router-view v-if="isRouterAlive"/> </div> </template> <script> export default { name: 'App', provide() { return { reload: this.reload//調用reload方法 } }, data() { return { isRouterAlive: true//一開始router-view爲true } },
  <span class="hljs-attr" style="line-height: 26px;">methods</span>: {
    reload() {
      <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">false</span>
         <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">//在修改數據以後使用 $nextTick,則能夠在回調中獲取更新後的 DOM</span>
      <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.$nextTick(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">()</span> =&gt;</span> {
        <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">true</span>
      })
    }
  }
}
複製代碼
複製代碼<span class="hljs-attr" style="line-height: 26px;">methods</span>: { reload() { <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">false</span> <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">//在修改數據以後使用 $nextTick,則能夠在回調中獲取更新後的 DOM</span> <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.$nextTick(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">()</span> =&gt;</span> { <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">this</span>.isRouterAlive = <span class="hljs-literal" style="color: #008080; line-height: 26px;">true</span> }) } } } 複製代碼</script> 複製代碼

12.2在頁面操做
export default {
      name: 'newproduct',
      inject:['reload'],//在export default下面加上這一段
      method:{
        //調用App.vue下的this.reload()方法,來改變v-if的狀態
        clickDiv(){//刷新按鈕調用的方法
          this.reload()
        }
      }
複製代碼

參考文檔:如何實現 vue 中不跳轉不閃動頁面刷新?provide /inject 完美解決方案

十3、vue動態綁定 class

13.1 對象方法
:class="{ 'active': isActive }"
複製代碼

13.2 判斷是否綁定一個active

:class="{'active':isActive==-1}"  
或者
:class="{'active':isActive==index}"
複製代碼
13.3綁定並判斷多個
第一種(用逗號隔開)
:class="{ 'active': isActive, 'sort': isSort }"
複製代碼
第二種(放在 data 裏面)
:class="classObject"
data() {
 return {
  classObject: {
   active: true,
   sort: false
  }
 }
}
複製代碼
第三種(使用 computed 屬性)
:class="classObject"
data() {
  return {
   isActive: true,
   isSort: false
  }
 },
 computed: {
  classObject: function() {
   return {
    active: this.isActive,
    sort: this.isSort
   }
  }
 }
複製代碼
13.4數組方法
1.單純數組
:class="[isActive,isSort]"
複製代碼
data() {
 return {
  isActive: 'active',
  isSort: 'sort'
 }
}
複製代碼

數組與三元運算符結合判斷選擇須要的class 三元運算符後面的「:」兩邊的class須要加上單引號

:class="[isActive?'active':'']"
複製代碼

或者

:class="[isActive==1?'active':'']"
複製代碼

或者

:class="[isActive==index?'active':'']"
複製代碼

或者

:class="[isActive==index?'active':'otherActiveClass']"
複製代碼
13.5 數組對象結合動態判斷

//前面這個 active 在對象裏面能夠不加單引號,後面這個 sort 要加單引號

:class="[{ active: isActive }, 'sort']"
複製代碼

或者

:class="[{ active: isActive==1 }, 'sort']"
複製代碼

或者

:class="[{ active: isActive==index }, 'sort']"
複製代碼

應用於組件 若是直接在自定義組件中使用 class 或 :class,那麼樣式規則就會直接應在這個組件的根元素上。

<div id="app">
    <text-component :class="{'isStrong':isStrong}"></text-component>
</div>
複製代碼
<script>
    Vue.component('text-component', {
        template: '<p class="content">不懂基因測序的學霸不是好的人工智能公司 CEO</p>'
    });
    var app = new Vue({
        el: '#app',
        data: {
            isStrong: true
        }
    });
</script>
複製代碼

參考文檔01 參考文檔02

style三元表達式

<span v-bind:style="{'display':config.isHaveSearch ? 'block':'none'}" >動態綁定樣式</span> 複製代碼

參考文檔

也可使用 v-bind:style 或 :style 直接給 HTML 元素綁定樣式,它也有對應的對象語法與數組語法。

<div id="app">
    <div :style="border"></div>
</div>
複製代碼
<script>
    var app = new Vue({
        el: '#app',
        data: {
            border:{
                border:'1px solid #00F',
                textShadow:'0 0 .3em gray'
            }
        }
    });
</script>
複製代碼

由於 JS 屬性不支持短橫分隔命名,因此咱們這裏使用 CSS 也支持的駝峯命名法。

參考文檔

計算屬性computed

例:反轉字符串:
<div id="app">
  <p>原始字符串: {{ message }}</p>
  <p>計算後反轉字符串: {{ reversedMessage }}</p>
</div>
複製代碼
<script>
var vm = new Vue({
  el: '#app',
  data: {
    message: 'Runoob!'
  },
  computed: {
    // 計算屬性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 實例
      return this.message.split('').reverse().join('')
    }
  }
})
</script> 複製代碼

咱們可使用 methods 來替代 computed,效果上兩個都是同樣的,可是 computed 是基於它的依賴緩存,只有相關依賴發生改變時纔會從新取值。而使用 methods ,在從新渲染的時候,函數總會從新調用執行。。換句話說,computed 是局部渲染,而 methods 是所有渲染 區別:

  • 1.methods是個方法,好比你點擊事件要執行一個方法,這時候就用methods,
  • 2.computed是計算屬性,實時響應的,好比你要根據data裏一個值隨時變化作出一些處理,就用computed。
  • 3.咱們能夠將同一函數定義爲一個方法而不是一個計算屬性。兩種方式的最終結果確實是徹底相同的。然而,不一樣的是計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時纔會從新求值。這就意味着只要 message 尚未發生改變,屢次訪問 reversedMessage 計算屬性會當即返回以前的計算結果,而沒必要再次執行函數。
  • 4.methods必須須要必定的條件去觸發,而computed則不須要.
  • 5.computed依賴緩存,若是不須要常常變更的用computed,須要常常變更的用methods。若是你須要傳參數,就用methods。

computed

computed 屬性默認只有 getter ,不過在須要時你也能夠提供一個 setter :

var vm = new Vue({
 el: '#app',
 data: {
  name: 'Google',
  url: 'http://www.google.com'
 },
 computed: {
  site: {
   // getter
   get: function() {
    return this.name + ' ' + this.url
   },
   // setter
   set: function(newValue) {
    var names = newValue.split(' ')
    this.name = names[0]
    this.url = names[names.length - 1]
   }
  }
 }
})
複製代碼
// 調用 setter, vm.name 和 vm.url 也會被對應更新
vm.site = 'http://www.runoob.com';
document.write('name: ' + vm.name);
document.write('<br>');
document.write('url: ' + vm.url);
複製代碼

從實例運行結果看在運行 vm.site = 'http://www.runoob.com'; 時,setter 會被調用, vm.name 和 vm.url 也會被對應更新。

十4、style樣式綁定

class 與 style 是 HTML 元素的屬性,用於設置元素的樣式,咱們能夠用 v-bind 來設置樣式屬性。 Vue.js v-bind 在處理 class 和 style 時, 專門加強了它。表達式的結果類型除了字符串以外,還能夠是對象或數組。

14.1 class 屬性綁定

咱們能夠爲 v-bind:class 設置一個對象,從而動態的切換 class:

<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
</style>
複製代碼
<div id="app">
  <div v-bind:class="{ active: isActive }"></div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true
  }
})
</script> 複製代碼

例:text-danger 類背景顏色覆蓋了 active 類的背景色:

方法一:在對象中傳入更多屬性用來動態切換多個 class 。
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>
複製代碼
<div id="app">
  <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">
  </div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true,
    hasError: true
  }
})
</script> 複製代碼
方法二:直接綁定數據裏的一個對象:
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>
複製代碼
<div id="app">
  <div v-bind:class="classObject"></div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    classObject: {
      active: true,
      'text-danger': true
    }
  }
})
</script> 複製代碼
方法三:綁定返回對象的計算屬性:
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>
複製代碼
<div id="app">
  <div v-bind:class="classObject"></div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
  isActive: true,
  error: null
  },
  computed: {
    classObject: function () {
      return {
        active: this.isActive && !this.error,
        'text-danger': this.error && this.error.type === 'fatal',
      }
    }
  }
})
</script> 複製代碼
方法四:數組語法
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>
複製代碼
<div id="app">
    <div v-bind:class="[activeClass, errorClass]"></div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
})
</script> 複製代碼

還可使用三元表達式來切換列表中的 class : errorClass 是始終存在的,isActive 爲 true 時添加 activeClass 類:

<style>
.text-danger {
    width: 100px;
    height: 100px;
    background: red;
}
.active {
    width: 100px;
    height: 100px;
    background: green;
}
</style>
複製代碼
<div id="app">
    <div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true,
    activeClass: 'active',
    errorClass: 'text-danger'
  }
})
</script> 複製代碼

style樣式邦定

v-bind:style直接設置樣式:

<div id="app">
    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鳥教程</div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    activeColor: 'green',
    fontSize: 30
  }
})
</script> 複製代碼

也能夠直接綁定到一個樣式對象:

<div id="app">
  <div v-bind:style="styleObject">菜鳥教程</div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    styleObject: {
      color: 'green',
      fontSize: '30px'
    }
  }
})
</script> 複製代碼

v-bind:style 可使用數組將多個樣式對象應用到一個元素上:

<div id="app">
  <div v-bind:style="[baseStyles, overridingStyles]">菜鳥教程</div>
</div>
複製代碼
<script>
new Vue({
  el: '#app',
  data: {
    baseStyles: {
      color: 'green',
      fontSize: '30px'
    },
    overridingStyles: {
      'font-weight': 'bold'
    }
  }
})
</script> 複製代碼

參考文檔

十5、vue組件參數傳遞:

Vue 組件間通訊包括:父子組件間通訊,兄弟組件間通訊以及模塊之間通訊等。Vue 是數據驅動視圖更新的框架, 因此對於 Vue 來講組件間的數據通訊很是重要。Vue 實現組件間通訊有不少方式,今天我來給你們講解一下父子組件間通訊:props 和$emit。

15.1.子組件向父組件傳遞參數;

image
image

子組件 A:

<template>
      <div class="childA-wrapper"> 子組件A </div>
    </template>
    <script> export default { data() { return { childA: '我是組件A傳過來的值' } }, created: function() {}, mounted() { this.sendDataParent() }, methods: { sendDataParent() { // getChildDataA是在父組件on監聽的方法 // 第二個參數this.childA是須要傳的值 this.$emit('getChildDataA', this.childA) } } } </script>
 複製代碼

子組件 B:

<template>
  <div class="childB-wrapper"> 子組件B </div>
</template>
 <script> export default { data() { return { childB:'我是組件B傳過來的值' } }, created:function() { }, mounted(){ this.sendDataParent() }, methods: { sendDataParent() { // getChildDataB是在父組件on監聽的方法 // 第二個參數this.childB是須要傳的值 this.$emit('getChildDataB', this.childB) } } } </script>  複製代碼

父組件:

<template>
        <div> <v-childA v-on:getChildDataA="getChildDataA"></v-childA> <v-childB v-on:getChildDataB="getChildDataB"></v-childB> <div>獲取組件A傳過來的值:{{childAValue}}</div> <div>獲取組件B傳過來的值:{{childBValue}}</div> </div>
    </template>
 <script> import childA from '@/components/childA.vue' import childB from '@/components/childB.vue' export default { data() { return { childAValue:'', childBValue:'', } }, methods: { getChildDataA(childA){ console.log(childA) this.childAValue=childA }, getChildDataB(childB){ console.log(childB) this.childBValue=childB } }, components: { 'v-childA': childA, 'v-childB': childB} } </script>  複製代碼

15.二、父組件向子組件傳遞參數

image
image
父組件:
<template>
        <div> <v-childA></v-childA> <v-childB :sendBData="sendB"></v-childB> </div>
    </template>
 <script> import childA from '@/components/childA.vue' import childB from '@/components/childB.vue' export default { data() { return { sendB:'父組件向B組件傳遞的參數' } }, methods: { }, components: { 'v-childA': childA, 'v-childB': childB} } </script>  複製代碼
子組件 B:
<template>
  <div class="childB-wrapper"> 子組件B:{{sendBData}} </div>
</template>
<script> export default { data() { return {} }, created: function() {}, mounted() {}, methods: {}, props: { sendBData: String, required: true } }  </script>  複製代碼

15.三、非父子組件進行傳值;

image
image
bus.js
import Vue from 'vue'
  export default new Vue()
 複製代碼
組件 childB:
<template>
    <div class="childB-wrapper"> </div>
  </template>
  <script> import Bus from '@/common/bus.js' export default { data() { return { childB: '我是組件B的內容' } }, created: function() {}, mounted() { this.elementByValue() }, methods: { elementByValue: function () { Bus.$emit('val', this.childB) } } }  </script> 複製代碼
##### 組件 childA:
 <template> <div class="childA-wrapper"> A組件:<span>{{childB}}</span> </div> </template> <script> import Bus from '@/common/bus.js' export default { data() { return { childB: '' } }, created: function() {}, mounted() { var that = this // 用 $on事件來接收參數 Bus.$on('val', (data) => { console.log(data) that.childB = data }) } }  </script> 複製代碼

更多請查看:你不知道的vue組件傳值方式

16.vue腳手架配置預渲染,prerender-spa-plugin 配置

用到插件:cnpm install prerender-spa-plugin --save 腳手架 2.0:(本身的是 2.0)

16.1 build/webpack.prod.conf.js 配置
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const webpackConfig = merge(baseWebpackConfig, {
 plugins: [
  // vue-cli 生成的配置就有了
  new HtmlWebpackPlugin({
   filename: config.build.index,
   template: 'index.html',
   inject: true,
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
   },
   chunksSortMode: 'dependency'
  }),
  // 配置 PrerenderSPAPlugin
  new PrerenderSPAPlugin({
   // 生成文件的路徑,也能夠與 webpakc 打包的一致。
   staticDir: path.join(\_\ _dirname, '../dist'),
 // 對應本身的全部路由文件,好比 index 有參數,就須要寫成 /index/param1。這個其實不須要;千萬不要加'/'這個 嵌套路由得 commonquestion 直接寫便可 routes: ['index', '...', '/commonQuestion', '/commonQuestion/questionList', '/commonQuestion/questionDetailInfo'], // ; renderer: new Renderer({ inject: { // 可選;最好仍是用 foo: 'bar' }, headless: false, // 可選;最好用 renderAfterTime: 5000, // 經過實踐是必選 官網說可選有誤 必定要必選 renderAfterDocumentEvent: 'render-event' // 可選;最好用 }) }), ] }) 複製代碼
16.2.路由得 index.js 添加屬性:
​ mode:‘history’,
複製代碼
修改config/index.js 中的build的 assetsPublicPath: ‘/’ ;否則會致使刷新頁面路徑錯亂致使樣式或者js丟失;
 修改main.js  new Vue({ el: '#app', router, store, // 若是須要了切記引入啊 切記須要掛載的所有掛載上去 render: h => h(App), mounted () { document.dispatchEvent(new Event('render-event')) } }) 複製代碼
16.3.build/webpack.prod.conf.js 配置
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const path = require('path');
module.exports = {
 configureWebpack: config => {
  if (process.env.NODE_ENV !== 'production') return;
  return {
   plugins: [
    new PrerenderSPAPlugin({
     // 生成文件的路徑,也能夠與 webpakc 打包的一致。
     // 下面這句話很是重要!!!
     // 這個目錄只能有一級,若是目錄層次大於一級,在生成的時候不會有任何錯誤提示,在預渲染的時候只會卡着不動。
     staticDir: path.join(\_\ _dirname, 'dist'),
     // 對應本身的路由文件,好比 a 有參數,就須要寫成 /a/param1。
     routes: ['/', '/product', '/about'],
     // 這個很重要,若是沒有配置這段,也不會進行預編譯
     renderer: new Renderer({
      inject: {
       foo: 'bar'
      },
      headless: false,
      renderAfterTime: 5000, // 必選哈
      // 在 main.js 中 document.dispatchEvent(new Event('render-event')),二者的事件名稱要對應上。
      renderAfterDocumentEvent: 'render-event'
     })
    }),
   ],
  };
 }
}
複製代碼
16.4 main.js 配置
new Vue({
 router,
 store,
 render: h => h(App),
 mounted() {
  document.dispatchEvent(new Event('render-event'))
 }
}).\$mount('#app')
複製代碼

其餘修改同 2.0;

參考文檔

十6、vue SPA單頁面的 SEO 優化

vue-meta-info 
複製代碼

官方地址: monkeyWangs/vue-meta-info

1.安裝
npm install vue-meta-info --save
複製代碼
2.全局引入 vue-meta-info
import Vue from 'vue'
import MetaInfo from 'vue-meta-info'
 Vue.use(MetaInfo) 複製代碼
3.組件內靜態使用 metaInfo
<template>
  ...
</template> 複製代碼
<script>
  export default {
    metaInfo: {
      title: 'My Example App', // set a title
      meta: [{                 // set meta
        name: 'keyWords',
        content: 'My Example App'
      }]
      link: [{                 // set link
        rel: 'asstes',
        href: 'https://assets-cdn.github.com/'
      }]
    }
  }
</script> 複製代碼
4.若是你的 title 或者 meta 是異步加載的,那麼你可能須要這樣使用
<template>
  ...
</template> 複製代碼
<script>
  export default {
    name: 'async',
    metaInfo () {
      return {
        title: this.pageName
      }
    },
    data () {
      return {
        pageName: 'loading'
      }
    },
    mounted () {
      setTimeout(() => {
        this.pageName = 'async'
      }, 2000)
    }
  }
</script> 複製代碼
<meta name="參數" content="具體的描述">
複製代碼
5.meta標籤共有兩個屬性,分別是http-equiv屬性和name屬性
  1. name 屬性 name 屬性主要用於描述網頁,好比網頁的關鍵詞,敘述等。與之對應的屬性值爲 content,content 中的內容是對 name 填入類型的具體描述,便於搜索引擎抓取。 meta 標籤中 name 屬性語法格式是:
<meta name="參數" content="具體的描述">
複製代碼

其中 name 屬性共有如下幾種參數。(A-C 爲經常使用屬性)

A. keywords(關鍵字)

說明:用於告訴搜索引擎,你網頁的關鍵字。

<meta name="keywords" content="XX網,汽車,車主,評選">
複製代碼
B. description(網站內容的描述)
說明:用於告訴搜索引擎,你網站的主要內容。
複製代碼
<meta name="description" content="汽車評選,XX網,評選,汽車">
複製代碼
C.viewport(移動端的視口)

說明:這個屬性經常使用於設計移動端網頁。

舉例

<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
複製代碼
D. robots(定義搜索引擎爬蟲的索引方式)
說明:robots 用來告訴爬蟲哪些頁面須要索引,哪些頁面不須要索引。
content 的參數有 all,none,index,noindex,follow,nofollow。默認是 all。
複製代碼

舉例:

<meta name="robots" content="none">
複製代碼

具體參數以下:

1.none : 搜索引擎將忽略此網頁,等價於 noindex,nofollow。
2.noindex : 搜索引擎不索引此網頁。
3.nofollow: 搜索引擎不繼續經過此網頁的連接索引搜索其它的網頁。
4.all : 搜索引擎將索引此網頁與繼續經過此網頁的連接索引,等價於 index,follow。
5.index : 搜索引擎索引此網頁。
6.follow : 搜索引擎繼續經過此網頁的連接索引搜索其它的網頁。
複製代碼
E. author(做者)

說明:用於標註網頁做者 舉例:

<meta name="author" content="Lxxyx,841380530@qq.com">
複製代碼
F. generator(網頁製做軟件)

說明:用於標明網頁是什麼軟件作的 舉例: (不知道能不能這樣寫):

<meta name="generator" content="Sublime Text3">
複製代碼
G. copyright(版權)

說明:用於標註版權信息 舉例:

<meta name="copyright" content="Lxxyx"> //表明該網站爲Lxxyx我的版權全部。
複製代碼
H. revisit-after(搜索引擎爬蟲重訪時間)

說明:若是頁面不是常常更新,爲了減輕搜索引擎爬蟲對服務器帶來的壓力,能夠設置一個爬蟲的重訪時間。若是重訪時間太短,爬蟲將按它們定義的默認時間來訪問。 舉例:

<meta name="revisit-after" content="7 days" >
複製代碼
I. renderer(雙核瀏覽器渲染方式)

說明:renderer 是爲雙核瀏覽器準備的,用於指定雙核瀏覽器默認以何種方式渲染頁面。好比說 360 瀏覽器。 舉例:

<meta name="renderer" content="webkit"> //默認webkit內核
<meta name="renderer" content="ie-comp"> //默認IE兼容模式
<meta name="renderer" content="ie-stand"> //默認IE標準模式
複製代碼
6. http-equiv 屬性

http-equiv 至關於 HTTP 的做用,好比說定義些 HTTP 參數啥的。 meta 標籤中 http-equiv 屬性語法格式是:

<meta http-equiv="參數" content="具體的描述">
複製代碼

其中 http-equiv 屬性主要有如下幾種參數:

A. content-Type(設定網頁字符集)(推薦使用 HTML5 的方式)

說明:用於設定網頁字符集,便於瀏覽器解析與渲染頁面 舉例:

<meta http-equiv="content-Type" content="text/html;charset=utf-8">  //舊的HTML,不推薦
<meta charset="utf-8"> //HTML5設定網頁字符集的方式,推薦使用UTF-8 複製代碼
B. X-UA-Compatible(瀏覽器採起何種版本渲染當前頁面)

說明:用於告知瀏覽器以何種版原本渲染頁面。(通常都設置爲最新模式,在各大框架中這個設置也很常見。) 舉例:

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> //指定IE和Chrome使用最新版本渲染當前頁面
複製代碼
C. cache-control(指定請求和響應遵循的緩存機制)

用法 1.

說明:指導瀏覽器如何緩存某個響應以及緩存多長時間。這一段內容我在網上找了好久,但都沒有找到滿意的。 最後終於在 Google Developers 中發現了我想要的答案。

舉例:

<meta http-equiv="cache-control" content="no-cache">
複製代碼

共有如下幾種用法:

  • no-cache: 先發送請求,與服務器確認該資源是否被更改,若是未被更改,則使用緩存。
  • no-store: 不容許緩存,每次都要去服務器上,下載完整的響應。(安全措施)
  • public : 緩存全部響應,但並不是必須。由於 max-age 也能夠作到相同效果
  • private : 只爲單個用戶緩存,所以不容許任何中繼進行緩存。(好比說 CDN 就不容許緩存 private 的響應)
  • maxage : 表示當前請求開始,該響應在多久內能被緩存和重用,而不去服務器從新請求。例如:max-age=60 表示響應能夠再緩存和重用 60 秒。 參考連接:HTTP 緩存 用法 2.(禁止百度自動轉碼)

說明:用於禁止當前頁面在移動端瀏覽時,被百度自動轉碼。雖然百度的本意是好的,可是轉碼效果不少時候卻不盡人意。因此能夠在 head 中加入例子中的那句話,就能夠避免百度自動轉碼了。 舉例:

<meta http-equiv="Cache-Control" content="no-siteapp" />
複製代碼
D. expires(網頁到期時間)

說明:用於設定網頁的到期時間,過時後網頁必須到服務器上從新傳輸。 舉例:

<meta http-equiv="expires" content="Sunday 26 October 2016 01:00 GMT" />
複製代碼
E. refresh(自動刷新並指向某頁面)

說明:網頁將在設定的時間內,自動刷新並調向設定的網址。 舉例:

<meta http-equiv="refresh" content="2;URL=http://www.lxxyx.win/"> //意思是2秒後跳轉向個人博客
複製代碼
F. Set-Cookie(cookie 設定)

說明:若是網頁過時。那麼這個網頁存在本地的 cookies 也會被自動刪除。

<meta http-equiv="Set-Cookie" content="name, date"> //格式
<meta http-equiv="Set-Cookie" content="User=Lxxyx; path=/; expires=Sunday, 10-Jan-16 10:00:00 GMT"> //具體範例
複製代碼
相關文章
相關標籤/搜索