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)
})