VueFAQ

目錄

FAQ

資源

初始化工程2.x

初始化工程3.x

 創建一個項目

拉取 2.x 模板 (舊版本)

工程目錄

ie兼容包

webpack打包img

定義組件過濾器

全局過濾器和加載

深度監聽/對象以及內部屬性的監聽

改變數組的值

常見事件監聽

原生事件監聽

路由器簡單使用

嵌套路由的使用/二級頁問題

組件定義.vue文件

組件註冊

全局註冊

局部註冊

import路徑中包含的 "@"

組件prop雙向綁定

第一種方式/自定義事件

第二種方式/.sync修飾符

第三種方式:v-model

綁定Style中帶有圖片/圖片訪問不到

屬性有多個屬性值

綁定style

訪問根實例vue/$root

自定義事件在程序中監聽/組件間的通行

vue打包路徑問題/build不在服務器中打開空白/cordova打開爲空白

vue打包路徑問題/build不在服務器中打開空白---->cli-3.0

vue中使用scss、sass

屏幕適配問題/設計稿寬計算

阿里圖標庫

vscodeTab鍵不生效/emmet

操作dom/獲取到的數據不正確/$nextTick()

返回上一頁

各種數據url鏈接/路由跳轉路徑path/全局訪問

局域網訪問工程/非本機訪問

緩存/keep-alive/對router使用keep-alive

緩存滾動的位置/scrollTop

深度/穿透/子組件樣式/deep/>>>

組件緩存/keep-alive/路由下的狀態保存

組件全局的自動註冊/自動加載

返回上一頁/回退

全局https網絡請求/this.$https調用

子組件插槽問題?

方式1:個人

方式2:官網

路由守衛

1.路由器守衛

2.路由全局守衛

3.組件內守衛

4.守衛共享

跨域

異步路由/路由懶加載

父組件主動獲取子組件的數據和方法

子組件主動獲取父組件的數據和方法在子組件裏面通過

子組件無法獲取到父傳入的props

this.$el.offsetHeight獲取爲0

動態加載圖片/static

爲路由器加入動畫/animate/transition

基本操作

global.js

頁面切換動畫----結合官網的寫法

注意:沒有進入動畫

加上position:absolute後,動畫執行過程中抖動。

動畫執行過程中,header(position: fixed)部分不見了,動畫結束後顯示。

keep-alive沒必要添加include

vue計算屬性get和set的作用和使用場景

遮罩處理

Vue學習之x-template(單文件.vue不需要)

router跳轉不能獲取到參數

CSS Modules

使用1:$style 的計算屬性

使用2::class 的對象/數組語法:

使用3:通過 JavaScript 訪問

全局自動導入scss的function、變量、mixin\scss自動導入

子組件不刷新問題,created鉤子不執行

router-view和key

給函數添加抖動/封裝method

vue-cli打包出現代碼不分離,可以使用第二種形式\代碼分離的多種寫法

打包,基本配置

打包--瀏覽器緩存問題,每次發版本,出現不更新js文件情況

打包--文件太大,使用gzip壓縮

路由A進入下一級B,緩存A;路由B進入下一級C,緩存B;B回退到A不緩存B

讓webstorm支持jsx語法



FAQ

資源

vueApi https://cn.vuejs.org/v2/api/

vue指導 https://cn.vuejs.org/v2/guide/ 

devTools調試 https://github.com/vuejs/vue-devtools

router路由 https://router.vuejs.org/zh/

vuex https://vuex.vuejs.org/zh/

srr服務器渲染 https://ssr.vuejs.org/zh/

初始化工程2.x

//vue-cli是2.X版本
npm install -g vue-cli

vue init webpack

初始化工程3.x

//vue-cli是3.X版本
npm install -g @vue/cli
# OR
yarn global add @vue/cli

你還可以用這個命令來檢查其版本是否正確 (3.x):
vue --version

 創建一個項目

vue create hello-world

 

 

拉取 2.x 模板 (舊版本)

npm install -g @vue/cli-init
# `vue init` 的運行效果將會跟 `[email protected]` 相同
vue init webpack my-project

工程目錄

目錄"store"爲Vuex相關的文件

ie兼容包

npm i -s 'babel-polyfill'
import "babel-polyfill";------>注意import位置儘量靠前,必須vuex前面

webpack打包img

//把圖片包含進來
import png1 from '@/assets/666320.png';
import png2 from '@/assets/6pro320-220.png';
import png3 from '@/assets/pc-320-220-mi8se.png';
import png4 from '@/assets/ds50.png';
import png5 from '@/assets/ds320_220.png';


//使用
{   
          shopname: "手機",
          list:[
               png4,
               png5,
         ]
},

定義組件過濾器

filters: {

  numFilter(value) {

  // 截取當前數據到小數點後三位

    let transformVal = Number(value).toFixed(3)

    let realVal = transformVal.substring(0, transformVal.length - 1)

    // num.toFixed(3)獲取的是字符串

    return Number(realVal)

  }

}

全局過濾器和加載

過濾器定義"./filter/custom.js"

function numFilter(value) {

      // 截取當前數據到小數點後三位

        let transformVal = Number(value).toFixed(3)

        let realVal = transformVal.substring(0, transformVal.length - 1)

        // num.toFixed(3)獲取的是字符串

        return Number(realVal)

      }
/**
 * 
 * @param {*} Vue 
 * @param {*} custom 
 */
function init(Vue){
        Object.keys(this).forEach(key => {
            if(key!=='init') {
                Vue.filter(key, this[key]);
                // console.log(key,custom[key])
            }
          
        })
    }
export {numFilter ,init}

加載、使用"main.js"

import * as custom from './filters/custom'
custom.init(Vue);//加載過濾器

深度監聽/對象以及內部屬性的監聽

深度監聽
watch: {
  obj: {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    deep: true
  }
}
第一個handler:其值是一個回調函數。即監聽到變化時應該執行的函數。
第二個是deep:其值是true或false;確認是否深入監聽。(一般監聽時是不能監聽到對象屬性值的變化的,數組的值變化可以聽到。)
第三個是immediate:其值是true或false;確認是否以當前的初始值執行handler的函數。

改變數組的值


var target  = {};
Object.assign(target,item,{checked:val})                 
this.$set(this.list, index, target);

常見事件監聽

@click  |  @change  當前元素失去焦點並且元素的內容發生改變而觸發此事件  |  @blur  |  @focus 

原生事件監聽

@click.native  |  @mouseenter.native  |  @dbclick.native 。。。mousedown mouseup mouseover mouseout 

路由器簡單使用

./router/index.js

import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
import index from '@/views/index'
// import Code404 from '@/components/Code404'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      // name: 'index',
      component: index
    },
    {
      path: '*',
      // name: 'index',
      redirect: '/'
      // component: Code404
    }
  ]
})

main.js

import router from './router'
//放入根vue
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

嵌套路由的使用/二級頁問題

// router/index.js
import Index from '@/views/index'
import MainPage from '@/views/MainPage'
import My from '@/views/my'
import Order from '@/views/order'
import ClasstifyAll from '@/views/ClasstifyAll'
import Search from '@/views/search'
import url from '../global/url'
let nav = url.navigator;
export default new Router({
  routes: [
    {
      path: '/',
      // name: 'HelloWorld',
      redirect:'/mainpage/index'
    },
    /**
     * mainpage頁,主頁
     */
    {
      path: nav.mainPage.selfpath,
      name: 'MainPage',
      component: MainPage,
      children:[
        {
          path: nav.mainPage.children.indexPath,
          name: 'index',
          component: Index
        },
        {
          path: nav.mainPage.children.myPath,
          name: 'my',
          component: My
        },
        {
          path: nav.mainPage.children.orderPath,
          name: 'order',
          component: Order
        }
      ]
    },
    /**
     * classtifyAll頁,全部分類頁
     */
    {
      path: nav.classtifyAll,
      name: 'classtifyAll',
      component: ClasstifyAll,
    },
    {
      path: nav.searchPath,
      name: 'Search',
      component: Search,
    }
    
  ]
})

主頁中的子分頁(index、my、order等)需要以子頁形式存在,二級頁是跟主頁mainpage同級的,這樣在主頁子分頁中點擊了二級頁鏈接,才能使得二級頁全屏。

組件定義.vue文件

<template>
    <div class="root">
        
    </div>
    
</template>

<script>

export default {
  props:['itemObj'],
  data() {
    return {
      maxNum:99,
    };
  },
  methods:{
      del(){
          this.list.splice(this.index,1);
      },
  
  },
  computed: {
    totalPrice() {
      return this.itemObj.num * this.itemObj.price;
    }
  },
    watch:{
    //   checked:function(val){

    //   }
  },
  filters: {

}

};
</script>

<style scoped>
.root{
  display: flex;
  width: 1200px;
  /* background-color: #234566; */
  color: #000;
  font-size: 12px;
  padding: 10px;
  border: 1px solid #ddd;
}
</style>

組件註冊

全局註冊

Vue.component('my-component-name', {
  // ... 選項 ...
})

局部註冊

import ComponentA from '@/components/ComponentA.js'
//或者
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }


new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

import路徑中包含的 "@"

例如:"@/components/xxx.js" @在webpack中有定義,表示src目錄

組件prop雙向綁定

第一種方式/自定義事件

父組件中

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

子組件中

this.$emit('update:title', newTitle)

第二種方式/.sync修飾符

父組件中

<XXX v-bind:showFlag.sync="showFlag" >

子組件中

this.$emit('update:showFlag', false);

關閉eslint代碼檢測

在config/index.js目錄下

// useEslint: true,
   useEslint: false,

第三種方式:v-model

父組件 <aa class="abc" v-model='test' ></aa> 。

子組件

export default {
    props: {
      value: { // 必須要使用value,才能接受v-model綁定的值變化
     default: '',
    },
    },

    methods: {
      fn2 () {
        this.$emit('input', this.value+2) 
        // 這兒必須用input 發送數據,發送的數據纔會被父級v-model=“test”接受到
        //input才能被v-model監聽
      }
    }
  }

綁定Style中帶有圖片/圖片訪問不到

//使用require或者import導入,只有這樣,webpack打包纔會導入圖片,不然會出現圖片訪問不到
return {
                backgroundImage:'url(' + require('../../assets/2.jpg') + ')',
                backgroundPosition:this.bigDivx+'%' +' '+this.bigDivy+'%'
}

屬性有多個屬性值

// 空格隔開
backgroundPosition:this.bigDivx+'%' +' '+this.bigDivy+'%'

綁定style

<div class="zhezhao" :style="jisuanzuobiao" v-show="zhezhaoShow" ></div>

computed:{
        jisuanzuobiao(){
            let min = 0;
            let max = 500;
            let zhezhaoY =  this.bianjie(this.zhezhaoY);
            let zhezhaoX =  this.bianjie(this.zhezhaoX);
            return {top:zhezhaoY+'px', left:zhezhaoX+'px'}
        }
}

訪問根實例vue/$root

通過this.$root

1.可以作爲全局的store使用,放入共享的數據

2.全局bus,自定義事件監聽和註冊,達到各個組件間的通信

自定義事件在程序中監聽/組件間的通行

$emit ("eventName",params) 發送一個事件

$on(eventName, eventHandler) 偵聽一個事件

$once(eventName, eventHandler) 一次性偵聽一個事件

$off(eventName, eventHandler) 停止偵聽一個事件

通過根vue完成通信操作(this.$root),

vue打包路徑問題/build不在服務器中打開空白/cordova打開爲空白

config/index.js文件修改一下位置

vue打包路徑問題/build不在服務器中打開空白---->cli-3.0

1.增加配置文件

2.去除路由器模式mode:history,默認爲mode:hash

vue中使用scss、sass

npm install node-sass --save-dev   //只需要這句
npm install sass-loader --save-dev
<style lang="scss" scoped>

屏幕適配問題/設計稿寬計算

//在需要使用的文件import 'vw_base.js'
//375爲設計稿寬,一般寬爲750,可以改成實際設計稿寬
$vm_base: 375; 
@function vw($px) {
    @return ($px / 375) * 100vw;
}

阿里圖標庫

在main.js中引入iconfont.css樣式

import 'xxx/xxx/xxx/iconfont.css'

vscodeTab鍵不生效/emmet

文件-首選項-設置
v1.5版本後配置如下 

"emmet.triggerExpansionOnTab": true,
"emmet.includeLanguages": {
"vue-html": "html",
"vue": "html"
}

 

設置代碼

"emmet.syntaxProfiles": {
  "vue-html": "html",
  "vue": "html"
}

操作dom/獲取到的數據不正確/$nextTick()

修改data中的數據,再到dom中獲取。這時候可能獲取到數據爲上一次的數據,dom還沒有完成刷新。使用this.$nextTick(funtion(){})

返回上一頁

$router.go(-1)

各種數據url鏈接/路由跳轉路徑path/全局訪問

1寫入一個文件中統一管理

2寫入在根vue中,統一'this.$url'調用,

3或者在main.js中   "var url = 導入的url"  變爲全局

//global/url.js

var url = {
  index: '/data/index',
  indexSwiper: '/data/indexSwiper',
  indexClass1: '/data/indexClass1',
  indexClass2: '/data/indexClass2',

  listing: '/data/listing',

  /**
   * 導航路徑
   */
  navigator: {
    mainPage: {
      selfpath: '/mainpage',
      children:{
        indexPath: 'index',
        indexFullPath:'/mainpage/index',
        orderPath: 'order',
        orderFullPath:'/mainpage/order',
        myPath: 'my',
        myFullPath:'/mainpage/my',
      }
      
    },
    classtifyAll:'/classtifyall',
    searchPath:'/search'
  }

}
export default url;

局域網訪問工程/非本機訪問

緩存/keep-alive/對router使用keep-alive

<keep-alive>
      <router-view></router-view>
</keep-alive>

緩存滾動的位置/scrollTop

對組件A先使用keep-alive後,在組件A內緩存div滾動位置

<template>
    <div class="index-root"  id="mainContent">
        ........
    </div>
</template>
data: function() {
    return {
      offsetTop:0,
    };
  },
activated() {
  // keep-alive組件 頁面進入的時候設置滾動高度
    document.getElementById("mainContent").scrollTop = this.offsetTop;
  },
beforeRouteLeave(to, from, next) {
   //組件離開的時候,獲取頁面滾動高度 
   this.offsetTop = document.getElementById('mainContent').scrollTop;
   next() 
},

深度/穿透/子組件樣式/deep/>>>

.header{
    
    position: relative;
    .mint-header{
        height: 16vw;
    /deep/ .mintui.mintui-back{ ////完成對子組件中類.mintui.mintui-back穿透
                font-size: 6vw;
            }
    }

組件緩存/keep-alive/路由下的狀態保存

注意:對組件A使用時,包含A組件的父B不能保存狀態,B被路由替換,則A也是無效的。

app.vue中使用keep-alive包裹router-view

<keep-alive include="mainpage" > //<----------在組件中取名字name='mainpage',這可以激活狀態保    
                                    存。相對於的不包含屬性 exclude=''
      <router-view></router-view>
</keep-alive>

router/index.js路由表中

/**
     * mainpage頁,主頁
     */
    {
      path: nav.mainPage.selfpath,
      name: 'mainpage',//  注意<---------App.vue中include='mainpage'不是對應這個name
      component: MainPage,
      children:[
        {
          path: nav.mainPage.children.indexPath,
          name: 'index',
          component: Index
        },
        {
          path: nav.mainPage.children.myPath,
          name: 'my',
          component: My
        },
        {
          path: nav.mainPage.children.orderPath,
          name: 'order',
          component: Order
        }
      ]
    },

在Mainpage.vue中定義name

export default {
  name: 'mainpage',// <-------定義名字與<keep-alive>中include保持一致
  data: function() {
    return {
      nameArray: ["首頁", "附近", "發現", "訂單", "我的"],
      selected: "首頁",
    //   offsetTop:0,
    };
  },
......

組件全局的自動註冊/自動加載

下面代碼會自動全局註冊'/components'下的組件,

注意:下列代碼依賴'lodash'

/**
 * 自動全局註冊componentS下的組件
 */
import {camelCase,upperFirst} from 'lodash'
import Vue from 'vue';
const requireComponent = require.context(
  '@/components', //當前基礎組件相對與main.js的相對位置
  false, //是否查詢子目錄
  /\.(vue|js)$/ 
)
requireComponent.keys().forEach(fileName => {
  const componentConfig = requireComponent(fileName) //獲取組建配置
  const componentName = 
      fileName.replace(/^\.\/(.*)\.\w+$/, '$1') // 剝去文件名開頭的 `'./` 和結尾的擴展名
  
  // const componentName = upperFirst( //獲取組件的 PascalCase 命名
  //   camelCase(
  //     fileName.replace(/^\.\/(.*)\.\w+$/, '$1') // 剝去文件名開頭的 `'./` 和結尾的擴展名
  //   )
  // )
      console.log(componentName)
  // 全局註冊組件
  Vue.component(
    componentName,
    componentConfig.default || componentConfig
  )
})

返回上一頁/回退

<div @click="$router.go(-1)">
       <slot></slot>
</div>

全局https網絡請求/this.$https調用

import axios from 'axios';
import url from '../global/url'
var https={
    listing:{
        request(){
            return axios.get(url.listing).then((res)=>res.data)
        }
    },
    registerInVue(Vue){
        Vue.prototype.$https = https
    }
}
export default https;

main.js

/**https訪問數據,爲index.js文件
 * 可以在子vue中通過 this.$url調用
 */
import https from  './https/index.js'
https.registerInVue(Vue);

子組件插槽問題?

父中傳入插槽所需內容,而內容中,有多個tag需要處理點擊事件,但是傳入的dom結果作用域是父的,然而需要傳入的dom響應子組件內的方法

注意:父組件模板的所有東西都會在父級作用域內編譯;子組件模板的所有東西都會在子級作用域內編譯。--官網

方式1:個人

mount()方法中,查找(querySelectAll(),)到需要點擊事件的node,並對node添加事件

方式2:官網

作用域插槽

提示:將子組件作用域方法值數組傳出給

路由守衛

1.路由器守衛

2.路由全局守衛

3.組件內守衛

4.守衛共享

router/guard.js

import store from '../store/index'
import {Toast} from 'mint-ui'
var guard = {
  /**
   * user守衛
   */
  userGuard:(to, from, next) => {
    if(store.getters['user/loginState']){
      next();
    }else{
      Toast({
        message: '請先登錄',
        position: 'bottom',
        duration: 3000
    });
      // next({ path: '/login' })
      next(false)
    }
  }
}

  export default guard;

router/index.js

import guard from './guard.js'//------->導入守衛處理函數

export default new Router({
  mode:'history',
  routes: [
.......
    /**
     * setting 個人設置頁面
     */
    {
      path:nav.settingPath,
      name:"setting",
      component:Setting,
      beforeEnter: guard.userGuard//------>引用共享函數guard.userGuard
                                  //------>路由器守衛
    },
     /**
     * my-collection 我的收藏頁面
     */
    {
      path:nav.myCollectionPath,
      name:"my-collection",
      component:MyCollection,
      //路由守衛
      beforeEnter: guard.userGuard//------>引用共享函數guard.userGuard
    },

.......
  ]
})

跨域

1.找到 vue項目目錄 > config > index.js

dev: {
    env: require('./dev.env'),
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
     '/api': {  // 這裏的 /api 是固定的 
          target: 'http://xxxx.cn', //你的服務器地址
          changeOrigin: true, //改變源 
          pathRewrite: { 
                '^/api': 'http://xxxx.cn'   // 意爲 用 /api 這個字符代替 後面的地址 在訪問接口時直接寫 /api ...... 就好了,這個/api可以是任意的字符。
           } 
      } 
    },
……
}

2.在開發過程中請求數據時直接用 /api (與上面pathRewrite定義的字符保持一致)開頭 +後面的接口。

axios.get('/api/xxx.json', function (res) { 
   console.log(res) 
}

 

異步路由/路由懶加載

以函數返回值形式導入,函數未執行

const Foo = () => import('./Foo.vue')

將導入函數放進router對象,按需求,異步導入執行導入函數

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

把組件按組分塊(可不做)

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

注意

如果您使用的是 Babel,你將需要添加 syntax-dynamic-import (當前新建工程已經存在改插件)插件,才能使 Babel 可以正確地解析語法。

 

父組件主動獲取子組件的數據和方法

1.調用子組件的時候 定義一個ref

<t-tab ref="xxx"></headerchild>//定義的名字xxx,父可以通過xxx調用t-tab
1
2.在父組件裏面通過

this.$refs.xxx.屬性----------->xxx同上
this.$refs.xxx.方法----------->xxx同上


子組件主動獲取父組件的數據和方法在子組件裏面通過

this.$parent.屬性
this.$parent.方法

 

子組件無法獲取到父傳入的props

1.父在mounted()中獲取的數據,修改需改綁定在props上的值,

2.錯誤的原因:子不可以在mounted中去獲取,不然報錯,因爲此時子已經mounted,父的mounted後修改數據在傳入晚了。

3.子應該在watch中完成獲取數據和操作。

this.$el.offsetHeight獲取爲0

原因1:當前vue被隱藏v-show=false;,獲取爲0。所以不能再初始化中運行獲取函數。

原因2:v-show=true;需要在$nextTick(function(){})中獲取,並且必須重新運行獲取函數。

動態加載圖片/static

將圖片放入static中就行,所有動態圖片都可以加載。如果放在assets中,就需要import或者require加載

爲路由器加入動畫/animate/transition

需要安裝animate.css動畫庫

基本操作

1.html結構

<template>
  ...
      <transition
          name="custom-classes-transition"   ------------>表示自定義動畫
          :enter-active-class="transitionInName"------------->表示進入時的動畫
          :leave-active-class="transitionOutName"------------>表示出去時的動畫
            >
    <keep-alive include="mainpage">
    <!-- <keep-alive > -->
        <router-view></router-view>
    </keep-alive>
      </transition>
  ...
</template>

2.

data() {
    return {
    transitionInName:'animated slideInRight',
    transitionOutName:'animated slideOutLeft'
    }
  },

。。。。。。。

watch: {
  '$route' (to, from) {
    if(this.$global.isRouterForward){------------->關鍵點
        //前進動畫
      this.transitionInName =  'animated slideInRight'
      this.transitionOutName = 'animated animated-delay slideOutLeft' 
    }else{
        //回退動畫
      this.transitionInName = 'animated  slideInLeft' 
      this.transitionOutName = 'animated animated-delay slideOutRight'
    }
    // 默認爲true
    this.$global.isRouterForward  = true;------------->關鍵點
  }
}

global.js

isRouterForward : true,

back的監聽,需要修改標誌位isRouterForward =false;表示執行回退動畫

this.$global.isRouterForward = false;
this.$router.back()

頁面切換動畫----結合官網的寫法

<template>
  <div id="app">
    <transition
        :enter-active-class="transitionInName"
        :leave-active-class="transitionOutName">
      <router-view />
    </transition>
    <SlideMenu></SlideMenu>
  </div>
</template>
<script >
import SlideMenu from "@/views/slide-menu/Index.vue";
export default {
  components: {
    SlideMenu
  },
  data() {
    return {
      transitionInName:'animated slideInRight',
      transitionOutName:'animated slideOutLeft'
    }
  },

  watch: {
    '$route'(to, from) {
      const toDepth = to.path.split('/').length
      const fromDepth = from.path.split('/').length
      this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
      if(toDepth === fromDepth){
        this.transitionInName = ''
        this.transitionOutName = ''
      }else if (toDepth > fromDepth) {
        //前進動畫
        this.transitionInName = 'animated slideInRight'
        this.transitionOutName = 'animated animated-delay slideOutLeft'
      } else {
        //回退動畫
        this.transitionInName = 'animated  slideInLeft'
        this.transitionOutName = 'animated animated-delay slideOutRight'
      }
    }
  }
}
</script>
<style lang="scss">
#app {
  /*font-family: "Microsoft Yahei",'Avenir', Helvetica, Arial, sans-serif;*/
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "微軟雅黑", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  /*padding: 30px;*/
  a {
    font-weight: bold;
    color: #2c3e50;
    &.router-link-exact-active {
      color: #42b983;
    }
  }
}

.animated {
  /*animation-duration: 60s !important;*/
  animation-duration: 100s !important;
  position: absolute;
}
</style>

注意:沒有進入動畫

因爲:進入的組件出去組件下方,對於手機界面,必然看不見。

.animated{//在
  animation-duration: 0.5s !impontant;---->加上權重
  position:absolute----------->動畫不執行、不顯示,<transition>加上absolute
}

或者官方解決辦法

給<transition>加屬性 mode='in-out'。mode='out-in'執行效果難受,先完全出去,在執行進入動畫

或者(。。。。。)只要前進時:右側進入動畫,後退時:右側出去動畫

 

加上position:absolute後,動畫執行過程中抖動。

因爲在執行動畫過程中,父的寬出現的變化。解決:給每一個route(每一頁)的根加上定寬。

動畫執行過程中,header(position: fixed)部分不見了,動畫結束後顯示。

動畫過程中,header部分跑到了頁面最上,相當於position:fixed 沒有效果。當動畫結束,position:fixed 產生效果,header部分回來。

解決辦法:頁高(height:100vh),header部分定高後,main部分(可滾動的部分),讓他撐開(flex:1),讓main部分顯示自己滾動條,而不是使用body的滾動條。

keep-alive沒必要添加include

我以爲會出現Android和react那種情況,每次路由push一個頁A,就會是一個新的頁A,導致棧中出現好多個A頁。事實上,棧中只會有一個頁A被重複彈出到棧頂。
 

vue計算屬性get和set的作用和使用場景

<input v-model="sosoInput" type="text" :placeholder="tips">
。。。。。。。
computed: {
    sosoInput: {
        // getter
        get: function () {
            return this.$store.state.common.searchKeyword;------->getter從store獲取數據
        },
        // setter
        set: function (newValue) {
            this.sosoInputValue = newValue;------->set將數據放入data的sosoInputValue中
        }
    }
},
。。。。。。。

例子中,沒有將數據返回到store,因爲需要最後‘確認’點擊確定的按鈕,纔會通過store.commit()提交出去

 

遮罩處理

處理遮罩問題,當點擊遮罩div的子,也會觸發closePopup()函數,

辦法1.在vue中加上'.self'修飾符

<div class="zhezhao" @click.self="closePopup">

辦法2.事件目標對象===.zhezhao對象,即點擊觸發在div.zhezhao上,而非div.zhezhao的子類

if($event.target===this.$el.querySelector('.zhezhao')){

Vue學習之x-template(單文件.vue不需要)

<html>
<head>
    <meta charset="utf-8">
    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
        <script type="text/x-template" id="my-component">

                <div>
                <p>This is the content of component</p>
                <p>Hello Vue!</p>
                </div>
                <div>Hello</div>
        </script>
    </div>
        <script>
            Vue.component('my-component',{
                    template:'#my-component'
            });
            var app=new Vue({
                el:"#app"
            });
        </script>
    </body>
    </html>

router跳轉不能獲取到參數

const router = new VueRouter({
  routes: [
    {
      path: '/user',
      name: 'user',
      component: User
    }
  ]
})

正確的

1.name和param傳遞參數和

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

2.path和query傳遞參數

<!-- 帶查詢參數,下面的結果爲 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

錯誤的--混用

<router-link :to="{ path: 'user', params: { userId: 123 }}">User</router-link>

CSS Modules

注意:不需要按照官網配置module:true;配合scss不需要配置;

<style> 上添加 module 特性:

<style module>
.red {
  color: red;
}
.bold {
  font-weight: bold;
}
</style>

使用1:$style 的計算屬性

<template>
  <p :class="$style.red">
    This should be red
  </p>
</template>

使用2::class 的對象/數組語法:

<template>
  <div>
    <p :class="{ [$style.red]: isRed }">
      Am I red?
    </p>
    <p :class="[$style.red, $style.bold]">
      Red and bold
    </p>
  </div>
</template>

使用3:通過 JavaScript 訪問

<script>
export default {
  created () {
    console.log(this.$style.red)
    // -> "red_1VyoJ-uZ"
    // 一個基於文件名和類名生成的標識符
  }
}
</script>

 

全局自動導入scss的function、變量、mixin\scss自動導入

yarn add  style-resources-loader -D

 vue.config.js

const path = require('path')

module.exports = {
    chainWebpack: config => {
        const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
        types.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)))
    },
}

function addStyleResource (rule) {
    rule.use('style-resource')
        .loader('style-resources-loader')
        .options({
            patterns: [
                path.resolve(__dirname, './src/css/g2.scss'),//./src/css/g2.scss目標文件位置
            ],
        })
}

 

子組件不刷新問題,created鉤子不執行

子組件不刷新問題,created鉤子不執行。

解決:給子組件綁定key值,當給子組件數據變化,相應的改變綁定key值。使得vue判斷這不是同一組件

 

router-view和key


做法與子組件刷新類似,給router-view綁定key值

1. 不設置 router-view 的 key 屬性
由於 Vue 會複用相同組件, 即 /page/1 => /page/2 或者 /page?id=1 => /page?id=2 這類鏈接跳轉時, 將不在執行created, mounted之類的鉤子, 這時候你需要在路由組件中, 添加beforeRouteUpdate鉤子來執行相關方法拉去數據

相關鉤子加載順序爲: beforeRouteUpdate

2. 設置 router-view 的 key 屬性值爲 $route.path
從/page/1 => /page/2, 由於這兩個路由的$route.path並不一樣, 所以組件被強制不復用, 相關鉤子加載順序爲:
beforeRouteUpdate => created => mounted

從/page?id=1 => /page?id=2, 由於這兩個路由的$route.path一樣, 所以和沒設置 key 屬性一樣, 會複用組件, 相關鉤子加載順序爲:
beforeRouteUpdate

3. 設置 router-view 的 key 屬性值爲 $route.fullPath
從/page/1 => /page/2, 由於這兩個路由的$route.fullPath並不一樣, 所以組件被強制不復用, 相關鉤子加載順序爲:
beforeRouteUpdate => created => mounted

從/page?id=1 => /page?id=2, 由於這兩個路由的$route.fullPath並不一樣, 所以組件被強制不復用, 相關鉤子加載順序爲:
beforeRouteUpdate => created => mounted

給函數添加抖動/封裝method

methods: {
    forbiddenPass: debounce(function (index, row) {
        //自己的代碼
    }, 300)
}

注1:這裏只能使用function聲明函數,如果使用箭頭函數,會出錯

注2:也就說明不管是抖動,其他用lodash包裝過的函數都可以這麼寫

 

vue-cli打包出現代碼不分離,可以使用第二種形式\代碼分離的多種寫法

第一種寫法:官方推薦第一種
component: (resolve) => { require(['./views/Home.vue'], resolve) }
第二種寫法,兼容性好
// component: () => import('./views/Home.vue')

打包,基本配置

const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
  publicPath: './', // 配置打包時的相對路徑
  productionSourceMap: false, // 生產環境是否生成 SourceMap
  devServer: {
    port: 8080,
    proxy: {
      '/dev-api': {
        // target: 'http://118.25.139.110:8088/', // target host
        target: 'http://api.thdtek.com', // target host
        // target: 'http://192.168.1.211:8080/', // target host
        ws: true, // proxy websockets
        changeOrigin: true, // needed for virtual hosted sites
        pathRewrite: {
          '^/dev-api': '' // rewrite path
        }
      }
    }
  },
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      return {
        plugins: [
          new CompressionPlugin({
            test: /\.js$|\.html$|\.css/, // 匹配文件名
            threshold: 10240, // 對超過10k的數據壓縮
            deleteOriginalAssets: false // 不刪除源文件
          })
        ]
        // cdn方式加載
        // externals: {
        //     'vue': 'Vue',
        //     'vue-router': 'VueRouter',
        //     'element-ui': 'ELEMENT',
        //     'normalize': 'normalize',
        // },
      }
    }
  },
  chainWebpack: config => {
    config.output.filename('js/[name].[hash]' + '.' + Date.now() + '.js').end()
    config.output.chunkFilename('js/[name].[chunkhash]' + '.' + Date.now() + '.js').end()
  }
}

打包--瀏覽器緩存問題,每次發版本,出現不更新js文件情況

在打包時,給輸出的名字帶上時間戳(Date.now())


module.exports = {
  chainWebpack: config => {
    config.output.filename('js/[name].[hash]' + '.' + Date.now() + '.js').end()
    config.output.chunkFilename('js/[name].[chunkhash]' + '.' + Date.now() + '.js').end()
  
}

打包--文件太大,使用gzip壓縮

const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      return {
        plugins: [
          new CompressionPlugin({
            test: /\.js$|\.html$|\.css/, // 匹配文件名
            threshold: 10240, // 對超過10k的數據壓縮
            deleteOriginalAssets: false // 不刪除源文件
          })
        ]
        // cdn方式加載
        // externals: {
        //     'vue': 'Vue',
        //     'vue-router': 'VueRouter',
        //     'element-ui': 'ELEMENT',
        //     'normalize': 'normalize',
        // },
      }
    }
  },
 
}

路由A進入下一級B,緩存A;路由B進入下一級C,緩存B;B回退到A不緩存B

讓webstorm支持jsx語法

<script type="text/jsx">

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