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 實例要控制的區域;
-
運行
cnpm i vue -S
將vue安裝爲運行依賴; -
運行
cnpm i vue-loader vue-template-compiler -D
將解析轉換vue的包安裝爲開發依賴; -
運行
cnpm i style-loader css-loader -D
將解析轉換CSS的包安裝爲開發依賴,因爲.vue文件中會寫CSS樣式; -
在
webpack.config.js
中,添加如下module
規則:
module: {
rules: [
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.vue$/, use: 'vue-loader' }
]
}
- 創建
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>
- 創建
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)
});
- 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項目中使用模板對象?
- 在
webpack.config.js
中添加resolve
屬性:
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
ES6中語法使用總結
-
使用
export default
和export
導出模塊中的成員; 對應ES5中的module.exports
和export
-
使用
import ** from **
和import '路徑'
還有import {a, b} from '模塊標識'
導入其他模塊 -
使用箭頭函數:
(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路由模塊
npm install vue-router
- 導入路由模塊:
import VueRouter from 'vue-router'
- 安裝路由模塊:
Vue.use(VueRouter);
- 導入需要展示的組件:
import login from './components/account/login.vue'
import register from './components/account/register.vue'
- 創建路由對象:
var router = new VueRouter({
routes: [
{ path: '/', redirect: '/login' },
{ path: '/login', component: login },
{ path: '/register', component: register }
]
});
- 將路由對象,掛載到 Vue 實例上:
var vm = new Vue({
el: '#app',
// render: c => { return c(App) }
render(c) {
return c(App);
},
router // 將路由對象,掛載到 Vue 實例上
});
- 改造App.vue組件,在 template 中,添加
router-link
和router-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 組件
- 導入所有MintUI組件:
import MintUI from 'mint-ui'
- 導入樣式表:
import 'mint-ui/lib/style.css'
- 在 vue 中使用 MintUI中的Button按鈕和Toast彈框提示:
Vue.use(MintUI)
- 使用的例子:
<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 上,下載現成的包,自己解壓出來,然後手動拷貝到項目中使用;
- 導入 MUI 的樣式表:
import '../lib/mui/css/mui.min.css'
- 在
webpack.config.js
中添加新的loader規則:
{ test: /\.(png|jpg|gif|ttf)$/, use: 'url-loader' }
- 根據官方提供的文檔和example,嘗試使用相關的組件
將項目源碼託管到oschina中
-
點擊頭像 -> 修改資料 -> SSH公鑰 如何生成SSH公鑰
-
創建自己的空倉儲,使用
git config --global user.name "用戶名"
和git config --global user.email ***@**.com
來全局配置提交時用戶的名稱和郵箱 -
使用
git init
在本地初始化項目 -
使用
touch README.md
和touch .gitignore
來創建項目的說明文件和忽略文件; -
使用
git add .
將所有文件託管到 git 中 -
使用
git commit -m "init project"
將項目進行本地提交 -
使用
git remote add origin 倉儲地址
將本地項目和遠程倉儲連接,並使用origin最爲遠程倉儲的別名 -
使用
git push -u origin master
將本地代碼push到倉儲中
App.vue 組件的基本設置
-
頭部的固定導航欄使用
Mint-UI
的Header
組件; -
底部的頁籤使用
mui
的tabbar
; -
購物車的圖標,使用
icons-extra
中的mui-icon-extra mui-icon-extra-cart
,同時,應該把其依賴的字體圖標文件mui-icons-extra.ttf
,複製到fonts
目錄下! -
將底部的頁籤,改造成
router-link
來實現單頁面的切換; -
Tab Bar 路由激活時候設置高亮的兩種方式:
- 全局設置樣式如下:
.router-link-active{
color:#007aff !important;
}
- 或者在
new VueRouter
的時候,通過linkActiveClass
來指定高亮的類:
// 創建路由對象
var router = new VueRouter({
routes: [
{ path: '/', redirect: '/home' }
],
linkActiveClass: 'mui-active'
});
實現 tabbar 頁籤不同組件頁面的切換
-
將 tabbar 改造成
router-link
形式,並指定每個連接的to
屬性; -
在入口文件中導入需要展示的組件,並創建路由對象:
// 導入需要展示的組件
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 輪播圖組件
- 假數據:
{
"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",
}],
}
}
- 自定義圖片懶加載指令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
})
- 引入輪播圖組件:
<!-- 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
獲取數據
-
運行
cnpm i vue-resource -S
安裝模塊 -
導入 vue-resource 組件
import VueResource from 'vue-resource'
- 在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)
})