Vue-入門到實戰(六)

Vue.js - day6

注意:

有時候使用npm i node-sass -D裝不上,這時候,就必須使用 cnpm i node-sass -D

在普通頁面中使用render函數渲染組件

<div id="app">
    <p>444444</p>
  </div>

  <script>

    var login = {
      template: '<h1>這是登錄組件</h1>'
    }

    // 創建 Vue 實例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      render: function (createElements) { // createElements 是一個 方法,調用它,能夠把 指定的 組件模板,渲染爲 html 結構
        return createElements(login)
        // 注意:這裏 return 的結果,會 替換頁面中 el 指定的那個 容器
      }
    });
  </script>
  

在webpack中配置.vue組件頁面的解析

// 總結梳理: webpack 中如何使用 vue :
// 1. 安裝vue的包:  cnpm i vue -S
// 2. 由於 在 webpack 中,推薦使用 .vue 這個組件模板文件定義組件,所以,需要安裝 能解析這種文件的 loader    cnpm i vue-loader vue-template-complier -D
// 3. 在 main.js 中,導入 vue 模塊  import Vue from 'vue'
// 4. 定義一個 .vue 結尾的組件,其中,組件有三部分組成: template script style
// 5. 使用 import login from './login.vue' 導入這個組件
// 6. 創建 vm 的實例 var vm = new Vue({ el: '#app', render: c => c(login) })
// 7. 在頁面中創建一個 id 爲 app 的 div 元素,作爲我們 vm 實例要控制的區域;

  1. 運行cnpm i vue -S將vue安裝爲運行依賴;

  2. 運行cnpm i vue-loader vue-template-compiler -D將解析轉換vue的包安裝爲開發依賴;

  3. 運行cnpm i style-loader css-loader -D將解析轉換CSS的包安裝爲開發依賴,因爲.vue文件中會寫CSS樣式;

  4. webpack.config.js中,添加如下module規則:


module: {

    rules: [

      { test: /\.css$/, use: ['style-loader', 'css-loader'] },

      { test: /\.vue$/, use: 'vue-loader' }

    ]

  }

  1. 創建App.js組件頁面:
    <template>
      <!-- 注意:在 .vue 的組件中,template 中必須有且只有唯一的根元素進行包裹,一般都用 div 當作唯一的根元素 -->
      <div>
        <h1>這是APP組件 - {{msg}}</h1>
        <h3>我是h3</h3>
      </div>
    </template>

    <script>
    // 注意:在 .vue 的組件中,通過 script 標籤來定義組件的行爲,需要使用 ES6 中提供的 export default 方式,導出一個vue實例對象
    export default {
      data() {
        return {msg: 'OK'}
      }
    }
    </script>

    <style scoped>//scoped:當前這個區域,局部的意思
    
    h1 {color: red;}
    
    </style>

  1. 創建main.js入口文件:

    // 導入 Vue 組件

    import Vue from 'vue'

// 注意: 在 webpack 中, 使用 import Vue from 'vue' 導入的 Vue 構造函數,功能不完整,只提供了 runtime-only 的方式,並沒有提供 像網頁中那樣的使用方式;
// import Vue from '../node_modules/vue/dist/vue.js'
// 回顧 包的查找規則:
// 1. 找 項目根目錄中有沒有 node_modules 的文件夾
// 2. 在 node_modules 中 根據包名,找對應的 vue 文件夾
// 3. 在 vue 文件夾中,找 一個叫做 package.json 的包配置文件
// 4. 在 package.json 文件中,查找 一個 main 屬性【main屬性指定了這個包在被加載時候,的入口文件】

    // 導入 App組件

    import App from './components/App.vue'



    // 創建一個 Vue 實例,使用 render 函數,渲染指定的組件

    var vm = new Vue({

      el: '#app',

      render: c => c(App)

    });

  1. webpack4版本時,會報錯vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.,需要修改webpack.config.js配置:
 var VueLoaderPlugin = require('vue-loader/lib/plugin')
 
 plugins:[
        new VueLoaderPlugin()
    ],

在使用webpack構建的Vue項目中使用模板對象?

  1. webpack.config.js中添加resolve屬性:
resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }

ES6中語法使用總結

  1. 使用 export defaultexport 導出模塊中的成員; 對應ES5中的 module.exportsexport

  2. 使用 import ** from **import '路徑' 還有 import {a, b} from '模塊標識' 導入其他模塊

  3. 使用箭頭函數:(a, b)=> { return a-b; }

// 這是 Node 中向外暴露成員的形式:
// module.exports = {}

// 在 ES6中,也通過 規範的形式,規定了 ES6 中如何 導入 和 導出 模塊
//  ES6中導入模塊,使用   import 模塊名稱 from '模塊標識符'    import '表示路徑'

// 在 ES6 中,使用 export default 和 export 向外暴露成員:
var info = {
  name: 'zs',
  age: 20
}

export default info

/* export default {
  address: '北京'
} */

// 注意: export default 向外暴露的成員,可以使用任意的變量來接收
// 注意: 在一個模塊中,export default 只允許向外暴露1次
// 注意: 在一個模塊中,可以同時使用 export default 和 export 向外暴露成員



export var title = '小星星'
export var content = '哈哈哈'

// 注意: 使用 export 向外暴露的成員,只能使用 { } 的形式來接收,這種形式,叫做 【按需導出】
// 注意: export 可以向外暴露多個成員, 同時,如果某些成員,我們在 import 的時候,不需要,則可以 不在 {}  中定義
// 注意: 使用 export 導出的成員,必須嚴格按照 導出時候的名稱,來使用  {}  按需接收;
// 注意: 使用 export 導出的成員,如果 就想 換個 名稱來接收,可以使用 as 來起別名;




// 在Node中 使用 var 名稱 = require('模塊標識符')
// module.exports 和 exports 來暴露成員

在vue組件頁面中,集成vue-router路由模塊

vue-router官網

npm install vue-router

  1. 導入路由模塊:

import VueRouter from 'vue-router'

  1. 安裝路由模塊:

Vue.use(VueRouter);

  1. 導入需要展示的組件:

import login from './components/account/login.vue'

import register from './components/account/register.vue'

  1. 創建路由對象:

var router = new VueRouter({

  routes: [

    { path: '/', redirect: '/login' },

    { path: '/login', component: login },

    { path: '/register', component: register }

  ]

});

  1. 將路由對象,掛載到 Vue 實例上:

var vm = new Vue({

  el: '#app',

  // render: c => { return c(App) }

  render(c) {

    return c(App);

  },

  router // 將路由對象,掛載到 Vue 實例上

});

  1. 改造App.vue組件,在 template 中,添加router-linkrouter-view

    <router-link to="/login">登錄</router-link>

    <router-link to="/register">註冊</router-link>



    <router-view></router-view>

組件中的css作用域問題

<style lang="scss" scoped>
/* 
普通的 style 標籤只支持 普通的 樣式,如果想要啓用 scss 或 less ,需要爲 style 元素,設置 lang 屬性 
只要 咱們的 style 標籤, 是在 .vue 組件中定義的,那麼,推薦都爲 style 開啓 scoped 屬性*/
body {
  div {
    font-style: italic;
  }
}
</style>

抽離路由爲單獨的模塊

1.main.js

// 導入 自定義路由模塊
import router from './router.js'

2.router.js

import VueRouter from 'vue-router'

// 導入 Account 組件
import account from './main/Account.vue'
import goodslist from './main/GoodsList.vue'

// 導入Account的兩個子組件
import login from './subcom/login.vue'
import register from './subcom/register.vue'

// 3. 創建路由對象
var router = new VueRouter({
  routes: [
    // account  goodslist
    {
      path: '/account',
      component: account,
      children: [
        { path: 'login', component: login },
        { path: 'register', component: register }
      ]
    },
    { path: '/goodslist', component: goodslist }
  ]
})

// 把路由對象暴露出去
export default router

使用 餓了麼的 MintUI 組件

Github 倉儲地址

Mint-UI官方文檔

  1. 導入所有MintUI組件:

import MintUI from 'mint-ui'

  1. 導入樣式表:

import 'mint-ui/lib/style.css'

  1. 在 vue 中使用 MintUI中的Button按鈕和Toast彈框提示:

Vue.use(MintUI)

  1. 使用的例子:

<mt-button type="primary" size="large">primary</mt-button>

Mint-UI中按需導入的配置方式

import 'mint-ui/lib/style.css'

// 按需導入 Mint-UI組件
import { Button } from 'mint-ui'
// 使用 Vue.component 註冊 按鈕組件
Vue.component(Button.name, Button)

使用 MUI 代碼片段

注意: MUI 不同於 Mint-UI,MUI只是開發出來的一套好用的代碼片段,裏面提供了配套的樣式、配套的HTML代碼段,類似於 Bootstrap; 而 Mint-UI,是真正的組件庫,是使用 Vue 技術封裝出來的 成套的組件,可以無縫的和 VUE項目進行集成開發;
因此,從體驗上來說, Mint-UI體驗更好,因爲這是別人幫我們開發好的現成的Vue組件;
從體驗上來說, MUI和Bootstrap類似;
理論上,任何項目都可以使用 MUI 或 Bootstrap,但是,MInt-UI只適用於Vue項目;

注意: MUI 並不能使用 npm 去下載,需要自己手動從 github 上,下載現成的包,自己解壓出來,然後手動拷貝到項目中使用;

官網首頁

文檔地址

  1. 導入 MUI 的樣式表:

import '../lib/mui/css/mui.min.css'

  1. webpack.config.js中添加新的loader規則:

{ test: /\.(png|jpg|gif|ttf)$/, use: 'url-loader' }

  1. 根據官方提供的文檔和example,嘗試使用相關的組件

將項目源碼託管到oschina中

  1. 點擊頭像 -> 修改資料 -> SSH公鑰 如何生成SSH公鑰

  2. 創建自己的空倉儲,使用 git config --global user.name "用戶名"git config --global user.email ***@**.com 來全局配置提交時用戶的名稱和郵箱

  3. 使用 git init 在本地初始化項目

  4. 使用 touch README.mdtouch .gitignore 來創建項目的說明文件和忽略文件;

  5. 使用 git add . 將所有文件託管到 git 中

  6. 使用 git commit -m "init project" 將項目進行本地提交

  7. 使用 git remote add origin 倉儲地址將本地項目和遠程倉儲連接,並使用origin最爲遠程倉儲的別名

  8. 使用 git push -u origin master 將本地代碼push到倉儲中

App.vue 組件的基本設置

  1. 頭部的固定導航欄使用 Mint-UIHeader 組件;

  2. 底部的頁籤使用 muitabbar;

  3. 購物車的圖標,使用 icons-extra 中的 mui-icon-extra mui-icon-extra-cart,同時,應該把其依賴的字體圖標文件 mui-icons-extra.ttf,複製到 fonts 目錄下!

  4. 將底部的頁籤,改造成 router-link 來實現單頁面的切換;

  5. Tab Bar 路由激活時候設置高亮的兩種方式:

  • 全局設置樣式如下:

	.router-link-active{

     	color:#007aff !important;

   }

  • 或者在 new VueRouter 的時候,通過 linkActiveClass 來指定高亮的類:

	// 創建路由對象

   var router = new VueRouter({

     routes: [

       { path: '/', redirect: '/home' }

     ],

     linkActiveClass: 'mui-active'

   });

實現 tabbar 頁籤不同組件頁面的切換

  1. 將 tabbar 改造成 router-link 形式,並指定每個連接的 to 屬性;

  2. 在入口文件中導入需要展示的組件,並創建路由對象:


    // 導入需要展示的組件

    import Home from './components/home/home.vue'

    import Member from './components/member/member.vue'

    import Shopcar from './components/shopcar/shopcar.vue'

    import Search from './components/search/search.vue'



    // 創建路由對象

    var router = new VueRouter({

      routes: [

        { path: '/', redirect: '/home' },

        { path: '/home', component: Home },

        { path: '/member', component: Member },

        { path: '/shopcar', component: Shopcar },

        { path: '/search', component: Search }

      ],

      linkActiveClass: 'mui-active'

    });

使用 mt-swipe 輪播圖組件

  1. 假數據:
{
  "data": {
    "message": [{
      "url": "http://www.itcast.cn/images/slidead/BEIJING/2017440109442800.jpg",
      "image": "http://www.itcast.cn/images/slidead/BEIJING/2017440109442800.jpg",
    }, {
      "url": "http://www.itcast.cn/images/slidead/BEIJING/2017511009514700.jpg",
      "image": "http://www.itcast.cn/images/slidead/BEIJING/2017511009514700.jpg",
    }, {
      "url": "http://www.itcast.cn/images/slidead/BEIJING/2017421414422600.jpg",
      "image": "http://www.itcast.cn/images/slidead/BEIJING/2017421414422600.jpg",
    }],
  }
}

  1. 自定義圖片懶加載指令v-lazyload

2.1安裝

npm install vue-lazyload --save

2.2引入

import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad)

or 

Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'dist/error.png',//圖片要自己放入
  loading: 'dist/loading.gif',//圖片要自己放入
  attempt: 1
})

  1. 引入輪播圖組件:

<!-- Mint-UI 輪播圖組件 -->

  <template>
  <div>
    <!-- 輪播圖區域 -->
    <mt-swipe :auto="4000">
      <mt-swipe-item v-for="item in lunbotuList" :key="item.url">
          <img v-lazy="item.image" alt="">
      </mt-swipe-item>
    </mt-swipe>
  </div>
</template>

<script>
import { Toast } from "mint-ui"

export default {
    data(){
        return{
           lunbotuList:[]
        }
    },
    created(){
        this.getLunbotu();
    },
    methods:{
      getLunbotu(){
          this.$http.get("https://www.easy-mock.com/mock/5c41678a0bb19c6a02e0175b/vuedemo/api/lunbo").
          then( result => {
              if(result.status === 200){
                  this.lunbotuList = result.data.data.message
              }else{
                  Toast("加載輪播圖失敗")
              }
          })
      }
    }
}
</script>

<style lang="scss" scoped>
.mint-swipe{
    height: 200px;

    .mint-swipe-item{

    &:nth-child(1){ background-color: red }
    &:nth-child(2){ background-color: blue }
    &:nth-child(3){ background-color: cyan }
}
img{
    width: 100%;
    height: 100%;
}
}

</style>


.vue組件中使用vue-resource獲取數據

  1. 運行cnpm i vue-resource -S安裝模塊

  2. 導入 vue-resource 組件


import VueResource from 'vue-resource'

  1. 在vue中使用 vue-resource 組件

Vue.use(VueResource);

封裝讀取文件的方法

// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我

const fs = require('fs')
const path = require('path')

// 這是普通讀取文件的方式
/* fs.readFile(path.join(__dirname, './files/1.txt'), 'utf-8', (err, dataStr) => {
  if (err) throw err
  console.log(dataStr)
}) */

// 初衷: 給定文件路徑,返回讀取到的內容
// 我們可以規定一下, callback 中,有兩個參數,第一個參數,是 失敗的結果;第二個參數是成功的結果;
// 同時,我們規定了: 如果成功後,返回的結果,應該位於 callback 參數的第二個位置,此時, 第一個位置 由於沒有出錯,所以,放一個 null;  
//                    如果失敗了,則 第一個位置放 Error對象,第二個位置放一個 undefined
function getFileByPath(fpath, callback) {
  fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    // 如果報錯了,進入if分支後,if後面的代碼就沒有必要執行了
    if (err) return callback(err)
    // console.log(dataStr)
    // return dataStr
    callback(null, dataStr)
  })
}

/* var result = getFileByPath(path.join(__dirname, './files/1.txt'))
console.log(result) */
getFileByPath(path.join(__dirname, './files/11.txt'), (err, dataStr) => {
  // console.log(dataStr + '-----')
  if (err) return console.log(err.message)
  console.log(dataStr)
})

封裝讀取文件的方法–提高版

// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我

const fs = require('fs')
const path = require('path')


function getFileByPath(fpath, succCb, errCb) {
  fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    if (err) return errCb(err)
    succCb(dataStr)
  })
}

// getFileByPath(path.join(__dirname, './files/11.txt'), function (data) {
//   console.log(data + '娃哈哈,成功了!!!')
// }, function (err) {
//   console.log('失敗的結果,我們使用失敗的回調處理了一下:' + err.message)
// })

// 需求: 先讀取文件1,再讀取文件2,最後再讀取文件3
// 回調地獄
// 使用 ES6 中的 Promise,來解決 回調地獄的問題;
// 問: Promise 的本質是要幹什麼的:就是單純的爲了解決回調地獄問題;並不能幫我們減少代碼量;
getFileByPath(path.join(__dirname, './files/1.txt'), function (data) {
  console.log(data)

  getFileByPath(path.join(__dirname, './files/2.txt'), function (data) {
    console.log(data)

    getFileByPath(path.join(__dirname, './files/3.txt'), function (data) {
      console.log(data)
    })
  })
})

Promise概念介紹

// 1. Promise 是一個 構造函數,既然是構造函數, 那麼,我們就可以  new Promise() 得到一個 Promise 的實例;
// 2. 在 Promise 上,有兩個函數,分別叫做 resolve(成功之後的回調函數) 和 reject(失敗之後的回調函數)
// 3. 在 Promise 構造函數的 Prototype 屬性上,有一個 .then() 方法,也就說,只要是 Promise 構造函數創建的實例,都可以訪問到 .then() 方法
// 4. Promise 表示一個 異步操作;每當我們 new 一個 Promise 的實例,這個實例,就表示一個具體的異步操作;
// 5. 既然 Promise 創建的實例,是一個異步操作,那麼,這個 異步操作的結果,只能有兩種狀態:
//  5.1 狀態1: 異步執行成功了,需要在內部調用 成功的回調函數 resolve 把結果返回給調用者;
//  5.2 狀態2: 異步執行失敗了,需要在內部調用 失敗的回調函數 reject 把結果返回給調用者;
//  5.3 由於 Promise 的實例,是一個異步操作,所以,內部拿到 操作的結果後,無法使用 return 把操作的結果返回給調用者; 這時候,只能使用回調函數的形式,來把 成功 或 失敗的結果,返回給調用者;
// 6. 我們可以在 new 出來的 Promise 實例上,調用 .then() 方法,【預先】 爲 這個 Promise 異步操作,指定 成功(resolve) 和 失敗(reject) 回調函數;


// 注意:這裏 new 出來的 promise, 只是代表 【形式上】的一個異步操作;
// 什麼是形式上的異步操作:就是說,我們只知道它是一個異步操作,但是做什麼具體的異步事情,目前還不清楚
// var promise = new Promise()


// 這是一個具體的異步操作,其中,使用 function 指定一個具體的異步操作
/* var promise = new Promise(function(){
  // 這個 function 內部寫的就是具體的異步操作!!!
}) */

const fs = require('fs')

// 每當 new 一個 Promise 實例的時候,就會立即 執行這個 異步操作中的代碼
// 也就是說,new 的時候,除了能夠得到 一個 promise 實例之外,還會立即調用 我們爲 Promise 構造函數傳遞的那個 function,執行這個 function 中的 異步操作代碼;
/* var promise = new Promise(function () {
  fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => {
    if (err) throw err
    console.log(dataStr)
  })
}) */


// 初衷: 給路徑,返回讀取到的內容
function getFileByPath(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {

      if (err) return reject(err)
      resolve(dataStr)

    })
  })
}

/* getFileByPath('./files/2.txt')
  .then(function (data) {
    console.log(data + '-------')
  }, function (err) {
    console.log(err.message)
  }) */

使用Promise解決回調地獄

const fs = require('fs')

function getFileByPath(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {

      if (err) return reject(err)
      resolve(dataStr)

    })
  })
}

// 先讀取文件1,在讀取2,最後讀取3
// 注意: 通過 .then 指定 回調函數的時候,成功的 回調函數,必須傳,但是,失敗的回調,可以省略不傳
// 這是一個 錯誤的示範,千萬不要這麼用; 硬是把 法拉利,開成了 拖拉機;
/* getFileByPath('./files/1.txt')
  .then(function (data) {
    console.log(data)

    getFileByPath('./files/2.txt')
      .then(function (data) {
        console.log(data)

        getFileByPath('./files/3.txt')
          .then(function (data) {
            console.log(data)
          })
      })
  }) */

// 讀取文件1
// 在上一個 .then 中,返回一個新的 promise 實例,可以繼續用下一個 .then 來處理


// 如果 ,前面的 Promise 執行失敗,我們不想讓後續的Promise 操作被終止,可以爲 每個 promise 指定 失敗的回調
/* getFileByPath('./files/11.txt')
  .then(function (data) {
    console.log(data)

    // 讀取文件2
    return getFileByPath('./files/2.txt')
  }, function (err) {
    console.log('這是失敗的結果:' + err.message)
    // return 一個 新的 Promise
    return getFileByPath('./files/2.txt')
  })
  .then(function (data) {
    console.log(data)

    return getFileByPath('./files/3.txt')
  })
  .then(function (data) {
    console.log(data)
  }).then(function (data) {
    console.log(data)
  }) */

// console.log('OKOKOK')



// 當 我們有這樣的需求: 哪怕前面的 Promise 執行失敗了,但是,不要影響後續 promise 的正常執行,此時,我們可以單獨爲 每個 promise,通過 .then 指定一下失敗的回調;

// 有時候,我們有這樣的需求,個上面的需求剛好相反:如果 後續的Promise 執行,依賴於 前面 Promise 執行的結果,如果前面的失敗了,則後面的就沒有繼續執行下去的意義了,此時,我們想要實現,一旦有報錯,則立即終止所有 Promise的執行;

getFileByPath('./files/1.txt')
  .then(function (data) {
    console.log(data)

    // 讀取文件2
    return getFileByPath('./files/22.txt')
  })
  .then(function (data) {
    console.log(data)

    return getFileByPath('./files/3.txt')
  })
  .then(function (data) {
    console.log(data)
  })
  .catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 執行失敗,則立即終止所有 promise 的執行,並 馬上進入 catch 去處理 Promise中 拋出的異常;
    console.log('這是自己的處理方式:' + err.message)
  })

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