vue2.0實踐總結

走在前端的大道上javascript


一.基礎

1.vue項目初始化

新建目錄 ss 和 test.js 文件:css

mkdir ss
cd ss
touch test.js

初始化目錄生成 package.jsonhtml

npm init

npm set 用來設置項目初始化時默認值前端

clipboard.png

$ npm set init-author-name 'your name'
$ npm set init-author-email 'your email'
$ npm set init-author-url 'your name'
$ npm set init-license 'MIT'

2.vue-cli 安裝

首先nodejs默認已經安裝vue

1.1 若是你的電腦是沒有安裝過vue-cli,那麼須要全局安裝執行npm install vue-cli -g,用vue -V查看版本,用vue list查看可選工具java

1.2 執行vue init webpack vuedemo3 在當前目錄下建立vuedemo3的項目
安裝選項能夠參照下圖node

clipboard.png

而後就能夠在目錄中看到生成vuedemo3文件夾webpack

clipboard.png

1.3 切換到vuedemo3文件夾
執行npm install,就下載了項目所須要的包依賴ios


3.vue掛載和渲染方式

new Vue({
        el:'#app',
        router,
        template:<App/>,
        components:{App}
    })
或
    new Vue({
        router,
        template:<App/>,
        components:{App}
    }).$mount("#app");
new Vue({
        router,
        render: h=>h(App)
    }).$mount("#app");
或
    new Vue({
        router,
        render: function(h){
            return h(App);
        )
    }).$mount("#app");

4.slot插槽

在子組件<hello>裏git

<slot name='world'></slot>

父組件使用

<hello>
    <span slot='world'>
        ....
    </span>
</hello>

5.獲取本地的json數據(模擬服務端返回數據)

在項目中須要使用vue-resource來與後臺進行數據交互,項目前期使用本地json數據來模仿後臺獲取數據的流程

說明:查看版本vue -V

操做方法:
a、項目結構:本地的json文件放在最外層和index.html同級,叫作db.json。
b、在build的dev-server.js進行加入代碼,位置如截圖:

var apiServer = express()
var bodyParser = require('body-parser')
apiServer.use(bodyParser.urlencoded({ extended: true }))
apiServer.use(bodyParser.json())
var apiRouter = express.Router()
var fs = require('fs')
apiRouter.route('/:apiName')
.all(function (req, res) {
  fs.readFile('./db.json', 'utf8', function (err, data) {
    if (err) throw err
    var data = JSON.parse(data)
    if (data[req.params.apiName]) {
      res.json(data[req.params.apiName])
    }
    else {
      res.send('no such api name')
    }

  })
})

apiServer.use('/api', apiRouter);
apiServer.listen(port + 1, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:' + (port + 1) + '\n')
})

clipboard.png

在瀏覽器中查看(我安裝了chrome遊覽器插件‘jsonView jsonViewer json formatter’,因此頁面上的格式是美化過的)

clipboard.png


6.vue組件綁定原生事件

vue使用element-ui的el-input監聽不了回車事件,固然其餘組件也有不能監聽原生事件的

<el-input v-model="taskSeachText" @keyup.enter="handleClick"></el-input>

須要在事件後面加上.native

<el-input v-model="taskSeachText" @keyup.enter.native="handleClick"></el-input>

總結:寫在一個封裝好的組件上,有些標籤的原生事件要.native 修飾符才能生效 #vue給組件綁定原生事件

clipboard.png

7.跨域請求配置

咱們平時本地前端開發環境dev地址大可能是 localhost:8080,然後臺服務器的訪問地址就有不少種狀況了,好比 127.0.0.1:8889,當前端與後臺進行數據交互時,天然就出現跨域問題(後臺服務沒作處理狀況下)。

如今經過在前端修改 vue-cli 的配置可解決:
vue-cli中的 client/config/index.js 下配置 dev選項的 {proxyTable}:

proxyTable: {
  // proxy all requests starting with /api to jsonplaceholder
  '/api': {
    target: 'http://127.0.0.1:8889/api',
    changeOrigin: true,
    onProxyReq (proxyReq, req, res) {
    }
  }
}

實際上這是由於腳手架使用了中間件 http-proxy-middleware

源地址 轉發地址
localhost:8080/api api.example.com/api
localhost:8080/api/notifications api.example.com/api/notifications

若是咱們要去掉 api.example.com的api路徑?

設置 pathRewrite

proxyTable: {
  '/api': {
    target: 'http://api.example.com',
    changeOrigin: true,
    pathRewrite: '^/api' : '',
    onProxyReq (proxyReq, req, res) {
    }
  }
}
源地址 轉發地址
localhost:8080/api api.example.com
localhost:8080/api/notifications api.example.com/notifications
代理的好處 代理的問題
解決開發時跨域問題 代碼須要設置環境變量,prod環境下不存在 http-proxy-middleware 中間件

8.axios 配置

新建 ajax.js

import axios from 'axios'
import store from '../store'
// 超時設置
const http = axios.create({
    timeout: 5000,
    baseURL: process.env.API_URL
})
或
// axios.defaults.baseURL = 'https://api.github.com';

// http request 攔截器
// 每次請求都爲http頭增長Authorization字段,其內容爲token
http.interceptors.request.use(
    config => {
        if (store.state.user.token) {
            config.headers.Authorization = `token ${store.state.user.token}`;
        }
        return config
    },
    err => {
        return Promise.reject(err)
    }
);
export default http

在入口文件 main.js 引入 ajax.js,並將其掛在到 Vue 全局方法下,即註冊到Vue原型上。這樣在.vue文件中直接使用this.$axios便可。固然你也能夠在每一個須要用到axios的文件中單獨引入。

import axios from './ajax'
...
Vue.prototype.$axios = axios

*.vue

methods: {
    // 請求到數據並賦值給data裏聲明的變量
      getData () {
        this.$axios.get('../../static/data/index.json').then((response) => {
          this.data = response.data
        }, (response) => {
          // error
        })
      }
    }

一些經常使用的庫也能夠掛載到 Vue 的原型上,避免在每一個.vue單頁面頻繁import引入

9.任意兩個組件之間的通訊

非父子間的組件通訊官方的叫法 global bus

// one.vue
<template>
  <div>
      這是one組件
      <button @click="commit">給two組件發送信息</button>
      <p> {{ message }}</p>
  </div>
</template>
<script type="text/javascript">
import { bus } from './bus'
export default {
    name: 'one',
    data () {
        return {
            message: '',
        }
    },
    methods:{
        commit () {
            bus.$emit('sendMsg',{
                msg: '這條信息來自於one'
            })
        }
    },
    mounted () {
        bus.$on('backMsg', (data) => {
            this.message = data.msg;
        })
    }
}
// two.vue
<template>
    <div @click="commit">
        <p>這是two組件<button @click="commit">給one組件發送信息</button></p>
        <p>{{ message }}</p>
    </div>
</template>
<script type="text/javascript">
import { bus } from './bus'
export default {
    name: 'two',
    data () {
        return {
            message: ''
        }
    },
    methods:{
        commit () {
            bus.$emit('backMsg',{
                msg: '這條信息來自於two'
            })
        }
    },
    mounted () {
        bus.$on('sendMsg', (data) => {
            this.message = data.msg;
        })
    }
}
</script>

最關鍵的bus,倒是最簡單的

// bus.vue
<script>
import Vue from 'vue'
export default {
    bus: new Vue(),
}
</script>

二.經常使用組件

1.vue-router

1.動態路由

routes:[
        {
            path:'/cart',
            name:'cart'
            component:Cart
        },
        {
            path:'/goods/:goodId/post/:name',
            name:'goods'
            component:goodsList
        }
    ]
    
    html:
        <span>{{$route.params.goodId}}</span>
        <span>{{$route.params.name}}</span>

2.嵌套路由

routes:[
        {
            path:'/goods',
            name:'goods'
            component:goodsList,
            children:[
                {
                    path:'title',    // 這裏title不能加 /
                    name:'title',
                    compoent: Title
                },
                {
                    path:'img',  
                    name:'img',
                    compoent: Image
                }
            ]
        }
    ]

    html:
        <router-link to="/goods/title">顯示標題</router-link>
        <router-link to="/goods/img">顯示圖片</router-link>
        <router-view></router-view>

備註:

<router-view></router-view>    標籤是盛放一級路由的
<router-link to="/goods/title"></router-link>   是路由跳轉

3.編程路由(經過js來實現頁面跳轉)

$router.push("name")     //    name=/title
    $router.push({path:"name"})
    $router.push({path:"name?goodId=123"}) 或者 $router.push({path:"name",query:{goodId:123}})
    $router.go(1)
html獲取參數
        <span>{{$route.query.goodId}}</span>

備註:
獲取頁面跳轉(js $router.push("name") )的參數 $route.query
獲取路由的參數$route.params

4.命名路由和命名的視圖

命名的路由

<router-link :to="{name:'cart'}"></router-link>
    <router-link :to="{name:'goods',params:{goodId:123}}"></router-link>

命名的視圖

<router-view></router-view>   
    <router-view name="title"></router-view>   
    <router-view name="img"></router-view>   

    routes:[
    {
        path:'/goods',
        name:'goods'
        components:{
            default:GoodsList,
            title:Title,
            img:Image
        }
    },{
        path:'/cart',
        name:'cart'
        component:Cart
    }]

2.vue-Resource

vue-Resource 和 axios區別:resource是掛載到vue實例裏面的axios是暴露了axios全局變量;axios的失敗回調經過catch捕獲

公用地址配置

http:{ //和methods 一級(並列)
    root: "http://"    
}

攔截器interceptors

munted:function(){
        Vue.http.interceptors.push(function(request,next){
                console.log("request init")
                next(function(response){
                    console.log("response init")
                    return response
                })
            })
    },
    methods:{
    
    }

clipboard.png

REST風格,7種API

1.get(url,[options])

methods:
    //同Vue.http.get 
    this.$http.get('package.json',{ //http://www.imooc.com/course/AjaxCourseMembers?ids=796
        params:{
            userId:"101"
        },
        headers:{
            token:"abcd"
        }
    }).then(res => {
        this.msg = res.data;
    },error =>{
        this.msg = error
    })

2.head(url,[options])

3.delete(url,[options])

4.jsonp(url,[options])

methods:
    this.$http.jsonp('http://www.imooc.com/course/AjaxCourseMembers?ids=796',{
    this.msg = res.data;
})

5.post(url,[body],[options])

methods:
    this.$http.post('package.json',{
            userId:"102"
        },{
        headers:{
            access_token:"abc"
        }
    }).then(res => {
        this.msg = res.data;
    },error =>{
        this.msg = error
    })

6.put(url,[body],[options])

7.patch(url,[body],[options])

8.自定義

methods:
    http:function(){
        this.$http({
            url:'package.json',
            methods:'GET',
            params:{
                userId:'103'
            },
            header:{
                token:'123'
            },
            timeout:50,
            before:function(){
                console.log("before init")
            }
        }).then(function(res){
            this.msg = res.data
        })
    }

clipboard.png

3.axios

vue-Resource 和 axios區別:resource是掛載到vue實例裏面的axios是暴露了axios全局變量;axios的失敗回調經過catch捕獲

公用地址配置

axios.defaults.baseURL = 'https://112...Server'

攔截器interceptors

munted:function(){
    axios.interceptors.request.use(function(request){
        console.log("request init")
        return request
    })
    axios.interceptors.response.use(function(response){
        console.log("request init")
        return response
    })
},
methods:{

}

1.axios.request(config)

2.axios.get(url[,config])

axios.get('package.json',{ //http://www.imooc.com/course/AjaxCourseMembers?ids=796
    params:{
        userId:"999"
    },
    headers:{
        token:"jack"
    }
}).then(res => {
    this.msg = res.data;
}).catch(error =>{
    console.log('error init')
})

3.axios.head(url[,config])

4.axios.delete(url[,config])

5.axios.options(url[,config])

6.axios.post(url[,[data[,config]])

axios.post('package.json',{ //http://www.imooc.com/course/AjaxCourseMembers?ids=796
        userId:"888"
    },{
    headers:{
        token:"tom"
    }
}).then(res => {
    this.msg = res.data;
}).catch(error =>{
    console.log('error init')
})

7.axios.put(url[,[data[,config]])

8.axios.patch(url[,[data[,config]])

9.自定義

methods:
    http:function(){
        axios({
            url:'package.json',
            methods:'post',
            params:{ // get方式傳參
                userId:'111'
            },
            data:{  // post方式傳參
                userId:'666'
            },
            header:{
                token:'http-test'
            }
        }).then(function(res){
            this.msg = res.data
        })
    }

4.babel-polyfill

5.babel-runtime

6.better-scroll

地址
當 better-scroll 碰見 Vue


7.fastclick

地址
FastClick 原理解析
中文翻譯


8.vue-lazyload

地址
中文文檔

9.stylus

同時須要stylus-loader


10.js-base64

1.在項目根目錄下安裝

cnpm install --save js-base64

2.在項目文件中引入

let Base64 = require('js-base64').Base64;

3.在項目文件中使用

Base64.encode('dankogai');  // ZGFua29nYWk=
Base64.encode('小飼弾');    // 5bCP6aO85by+
Base64.encodeURI('小飼弾'); // 5bCP6aO85by-

Base64.decode('ZGFua29nYWk=');  // dankogai
Base64.decode('5bCP6aO85by+');  // 小飼弾
// note .decodeURI() is unnecessary since it accepts both flavors
Base64.decode('5bCP6aO85by-');  // 小飼弾

11.js-md5

1.在項目根目錄下安裝

cnpm install --save js-md5

2.在項目文件中引入

import md5 from 'js-md5';

3.在項目文件中使用

md5(''); // d41d8cd98f00b204e9800998ecf8427e
md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6
md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0

// It also supports UTF-8 encoding
md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07

// It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
md5([]); // d41d8cd98f00b204e9800998ecf8427e
md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e

// Different output
md5(''); // d41d8cd98f00b204e9800998ecf8427e
md5.hex(''); // d41d8cd98f00b204e9800998ecf8427e
md5.array(''); // [212, 29, 140, 217, 143, 0, 178, 4, 233, 128, 9, 152, 236, 248, 66, 126]
md5.digest(''); // [212, 29, 140, 217, 143, 0, 178, 4, 233, 128, 9, 152, 236, 248, 66, 126]
md5.arrayBuffer(''); // ArrayBuffer
md5.buffer(''); // ArrayBuffer, deprecated, This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.

clipboard.png

clipboard.png
本節參考文章:vue中使用base64和md5


三.常見問題

1.vue-cli打包引起的 字體或圖片 丟失問題

解決本地和服務器上資源url解析的問題

問題描述:

1.在img中的圖片是徹底正確的, 但css中background-image: url()的圖片怎麼都找不到.
2.最尷尬的是: 在npm run dev的時候一切正常

clipboard.png

解決方法:

在 config/index.js 中修改 assetsPublicPath 爲 ./

在 build/utils.js 中的 ExtractTextPlugin.extract 傳入參數 publicPath: '../../'

2.axios的 post 請求後臺接受不到

axios的 post 請求後臺接受不到!axios默認是 json 格式提交,確認後臺是否作了對應的支持;
如果只能接受傳統的表單序列化,就須要本身寫一個轉義的方法...
固然還有一個更加省事的方案,裝一個小模塊qs

npm install qs -S


// 而後在對應的地方轉就好了..單一請求也行,攔截器也行...我是寫在攔截器的.
// 具體能夠看看我 axios 封裝那篇文章

//POST傳參序列化(添加請求攔截器)
Axios.interceptors.request.use(
  config => {
    // 在發送請求以前作某件事
    if (
      config.method === "post"
    ) {
      // 序列化
      config.data = qs.stringify(config.data); // ***** 這裏轉義
    }

    // 如果有作鑑權token , 就給頭部帶上token
    if (localStorage.token) {
      config.headers.Authorization = localStorage.token;
    }
    return config;
  },
  error => {
    Message({
      //  餓了麼的消息彈窗組件,相似toast
      showClose: true,
      message: error,
      type: "error.data.error.message"
    });
    return Promise.reject(error.data.error.message);
  }
);

3.element-ui 2.0 input組件輸入數字

element-ui 2.0 表單或者input組件 驗證輸入的數字檢測出來是string

數字類型的驗證須要在 v-model 處加上 .number 的修飾符,這是 Vue 自身提供的用於將綁定值轉化爲 number 類型的修飾符。el-input 的 type 屬性設置爲 "number"

<el-form-item label="年齡" prop="age">
    <el-input type="number" v-model.number="ruleForm2.age"></el-input>
</el-form-item>

4.element-ui 2.0 table組件 添加border屬性後多了滾動條

解決方法:

.el-table__body-wrapper, .el-table__footer-wrapper, .el-table__header-wrapper{
    width: 101%;
}

更多問題總結:

  1. Vue 脫坑記 - 查漏補缺...
  2. VUE使用element-ui所遇

參考文章1 , 參考文章2

相關文章
相關標籤/搜索