v-cloak
防止页面加载时出现闪烁问题
<script type="text/css">
[v - cloak] { display: none; }
</script>
<div id="app" v-cloak>
</div>
v-text
<div v-text='msg'></div>
<div v-text>{{msg}}</div>
v-html
v-html
,永不用在用户提交的内容上 <div v-html='msg1'></div>
v-pre
<div v-pre>{{msg}}</div>
v-once
执行一次性的插值【当数据改变时,插值处的内容不会继续更新】
<!-- 即使data里面定义了msg 后期我们修改了 仍然显示的是第一次data里面存储的数据即 Hello Vue.js -->
<span v-once>{{ msg}}</span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
v-model
双向数据绑定
v-model是一个指令,限制在 、
中使用
<div id="app">
<div>{{msg}}</div>
<div>
当输入框中内容改变的时候, 页面上的msg 会自动更新
<input type="text" v-model='msg'>
</div>
</div>
mvvm
v-on
<div>{{num}}</div>
<button v-on:click='num++'>点击</button>
<button @click='num++'>点击</button>
<!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
<!-- 2、如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,
并且事件对象的名称必须是$event -->
<button @click='handle(123,456,$event)'>点击1</button>
事件修饰符
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 即阻止冒泡也阻止默认事件 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
按键修饰符
在做项目中有时会用到键盘事件,在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on
在监听键盘事件时添加按键修饰符
<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- -当点击enter 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--当点击enter或者space时 时调用 `vm.alertMe()` -->
<input type="text" v-on:keyup.enter.space="alertMe" >
常用的按键修饰符
.enter => enter键
.tab => tab键
.delete (捕获“删除”和“退格”按键) => 删除键
.esc => 取消键
.space => 空格键
.up => 上
.down => 下
.left => 左
.right => 右
<script>
var vm = new Vue({
el:"#app",
methods: {
submit:function(){},
alertMe:function(){},
}
})
</script>
自定义修饰符别名
在Vue中可以通过config.keyCodes
自定义按键修饰符别名
<div id="app">
预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法
<input type="text" v-on:keydown.f5="prompt()">
</div>
<script>
Vue.config.keyCodes.f5 = 116;
let app = new Vue({
el: '#app',
methods: {
prompt: function() {
alert('我是 F5!');
}
}
});
</script>
v-bind 属性绑定
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
分支结构 v-if
<div id="app">
<div v-if='score>90'>优秀</div>
<div v-else-if='score>60'>良好</div>
<div v-else>不及格</div>
<br>
<!-- v-show控制显示与隐藏 -->
<div v-show='false'>v-show测试</div>
</div>
<script src="./js/vue.js"></script>
<script>
var lk = new Vue({
//el:元素挂载位置 data:模型数据(值是一个对象)
el: '#app',
data: {
score: 55
},
//函数要定义在methods中
methods: {
handle: function() {
this.url = 'https://cn.vuejs.org/v2/api/#v-on'
}
}
})
</script>
v-show 和 v-if的区别
循环结构 v-for
<div id="app">
<div>水果列表</div>
<ul>
<li v-for='item in fruits'>{{item}}</li>
</ul>
<ul>
//:k的作用:帮助Vue区分不同的元素 从而提高性能
<li :key='index' v-for='(item,index) in fruits'>{{item+'----'+index}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
var lk = new Vue({
//el:元素挂载位置 data:模型数据(值是一个对象)
el: '#app',
data: {
fruits: ['apple', 'orange', 'banana']
},
//函数要定义在methods中
methods: {
}
})
</script>
v-if
和 v-for
v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。key 的作用
表单
v-model
1.单选
<div>
<span>性别:</span>
<span>
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
</span>
</div>
2.多选 – hobby 要定义成数组 否则无法实现多选
<div>
<span>爱好:</span>
<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">写代码</label>
</div>
3.下拉框和文本
<div>
<span>职业:</span>
<select v-model='occupation' multiple>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
</div>
<div>
<span>个人简介:</span>
<textarea v-model='desc'></textarea>
</div>
表单修饰符
<input v-model.number="age" type="number">
<input v-model.trim="msg">
<input v-model.lazy="msg" >
自定义指令
Vue.directive('focus', {
inserted: function(el) {
// el表示指令所绑定的元素
el.focus();
}
});
自定义局部指令
//自定义局部指定
directives: {
color: {
bind: function(el, binding) {
el.style.backgroundColor = binding.value.color
}
}
}
计算属性 computed
//计算属性,需要有返回值
computed: {
方法名: function() {
return 返回值
}
}
//使用时直接写方法名 不需要跟括号
侦听属性 watch
//侦听
watch: {
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
过滤器 filter
过滤器三种使用方式
<div>{{msg | upper}}</div>
<div>{{msg | upper | lower}}</div>
<div :abc='msg | upper'>测试数据</div>
局部过滤器filters
//过滤器
filters: {
upper: function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
自定义过滤器filter
Vue.filter(‘过滤器名称’,函数)
Vue.filter('upper', function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
});
data
,而只是改变渲染的结果,并返回过滤后的版本生命周期
常用的 钩子函数
beforeCreate | 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 |
---|---|
created | 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 |
beforeMount | 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件 |
beforeUpdate | 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的 |
updated | 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的 |
beforeDestroy | 实例销毁之前调用 |
destroyed | 实例销毁后调用 |
数组变异方法
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
---|---|
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值 |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
替换数组
filter | filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
---|---|
concat | concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
slice | slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组 |
动态数组响应式数据
// Vue.set(vm.list, 2, 'lemon');
vm.$set(vm.list, 1, 'lemon');
// vm.info.gender = 'male';
vm.$set(vm.info, 'gender', 'female');
组件注册
1.全局注册
//注册组件
//如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是
//在普通的标签模板中, 必须使用短横线的方式使用组件
Vue.component('button-counter', {
//data必须是一个函数
data() {
return {
count: 0
}
},
//组件模板内容必须是单个跟元素
template: `
`,
methods: {
handle: function() {
this.count += 2
}
}
})
2.局部注册
var vm = new Vue({
el: '#app',
data: {
},
//局部组件,局部组件只能在注册他的父组件中使用
components: {
'hello-world': {
data: function() {
return {
msg: 'HelloWorld'
}
},
template: '{{msg}}'
};
}
});
组件传值
<div id="app">
<div :style='{fontSize: fontSize + "px"}'>{{pmsg}}div>
<menu-item :title='dome' content='hellow' @enlarge-text='handle($event)'>menu-item>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('menu-item', {
//props接收传递过来的值
props: ['title', 'content'],
data() {
return {
msg: '子组件'
}
},
template: `
{{msg+'----'+title+'----'+content}}
`
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件',
dome: '父组件传值',
fontSize: 10
},
methods: {
handle: function(val) {
// 扩大字体大小
this.fontSize += val;
}
}
});
script>
数据交互
<div id="app">
<div>父组件div>
<div>
<button @click='handle'>销毁事件button>
div>
<test-tom>test-tom>
<test-jerry>test-jerry>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
//提供事件中心
var hub = new Vue()
Vue.component('test-tom', {
data() {
return {
num: 0
}
},
template: `
TOM:{{num}}
点击
`,
methods: {
handle: function() {
//触发兄弟组件的事件
hub.$emit('jerry-event', 2)
}
},
mounted: function() {
// 监听事件
hub.$on('tom-event', (val) => {
this.num += val;
});
}
})
Vue.component('test-jerry', {
data() {
return {
num: 0
}
},
template: `
JERRY:{{num}}
点击
`,
methods: {
handle: function() {
//触发兄弟组件的事件
hub.$emit('tom-event', 1)
}
},
mounted() {
//监听事件
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function() {
//销毁事件
hub.$off('tom-event')
hub.$off('jerry-event')
}
}
});
script>
插槽
<div id="app">
<div>
<alert-box>bugalert-box>
<alert-box>abcalert-box>
<alert-box>alert-box>
<base-layout>
<p slot='header'>标题信息p>
<template slot='header'>
<p>标题信息1p>
template>
<p>主要内容1p>
<template slot='footer'>
<p>底部信息信息1p>
template>
base-layout>
div>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('alert-box', {
//通过slot设置插槽
template: `
ERROR:
默认内容
`
})
//具名插槽
Vue.component('base-layout', {
template: `
`
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
}
});
script>
作用域插槽
<div id="app">
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==2' class="current">{{slotProps.info.name}}strong>
<span v-else >{{slotProps.info.name}}span>
template>
fruit-list>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('fruit-list', {
props: ['list'],
template: `
{{item.name}}
`
})
var vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
name: 'apple'
}, {
id: 2,
name: 'orange'
}, {
id: 3,
name: 'banana'
}]
},
methods: {
}
});
script>
Promise
<script type="text/javascript">
/*
1. Promise基本使用
我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数,并且传入两个参数: resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数
*/
var p = new Promise(function(resolve, reject){
//2. 这里用于实现异步任务 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
//3. 正常情况
resolve('hello');
}else{
//4. 异常情况
reject('出错了');
}
}, 100);
});
// 5 Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数
// 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
p.then(function(data){
console.log(data)
},function(info){
console.log(info)
});
script>
基于Promise发送Ajax请求
<script type="text/javascript">
/*
基于Promise发送Ajax请求
*/
function queryData(url) {
# 1.1 创建一个Promise实例
var p = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
# 1.2 处理正常的情况
resolve(xhr.responseText);
}else{
# 1.3 处理异常情况
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
# 注意: 这里需要开启一个服务
# 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
# 1.4 想要继续链式编程下去 需要 return
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data){
console.log(data)
});
script>
Promise 基本AP
.then()
.catch()
.finally()
<script type="text/javascript">
function foo() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
// resolve(123);
reject('error');
}, 100);
})
}
// foo()
// .then(function(data){
// console.log(data)
// })
// .catch(function(data){
// console.log(data)
// })
// .finally(function(){
// console.log('finished')
// });
// --------------------------
// 两种写法是等效的
foo()
.then(function(data) {
console.log(data)
}, function(data) {
console.log(data)
})
//.finally()成功与否都会执行(尚且不是正式标准)
.finally(function() {
console.log('finished')
});
script>
Promise 静态方法
//Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.all([p1, p2, p3]).then(function(result) {
console.log(result)
})
//Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.race([p1, p2, p3]).then(function(result) {
console.log(result)
})
fetch
fetch('http://localhost:3000/books', {
method: 'post',
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data) {
//text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
return data.text()
})
.then(function(data) {
console.log(data);
})
fetchAPI 中 响应格式
JSON
,BLOB
或者TEXT
等等 /*
Fetch响应结果的数据格式
*/
fetch('http://localhost:3000/json').then(function(data){
// return data.json(); // 将获取到的数据使用 json 转换对象
return data.text(); // // 将获取到的数据 转换成字符串
}).then(function(data){
// console.log(data.uname)
// console.log(typeof data)
var obj = JSON.parse(data);
console.log(obj.uname,obj.age,obj.gender)
})
axios
// axios put 请求传参
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret) {
console.log(ret.data)
})
axios 全局配置
// 配置请求的基准URL地址
axios.defaults.baseURL = 'http://localhost:3000/';
// 配置请求头信息
axios.defaults.headers['mytoken'] = 'hello';
axios.get('axios-json').then(ret => {
console.log(ret.data.uname)
})
axios 拦截器
//请求拦截器
axios.interceptors.request.use(function(config) {
console.log(config.url)
config.headers.mytoken = 'nihao';
return config;
}, function(err) {
console.log(err)
})
//响应拦截器
axios.interceptors.response.use(function(res) {
// console.log(res)
var data = res.data;
return data;
}, function(err) {
console.log(err)
})
async 和 await
async
函数都会隐式返回一个promise
await
关键字只能在使用async
定义的函数中使用
# 1. async 基础用法
# 1.1 async作为一个关键字放到函数前面
async function queryData() {
# 1.2 await关键字只能在使用async定义的函数中使用 await后面可以直接跟一个 Promise实例对象
var ret = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve('nihao')
},1000);
})
// console.log(ret.data)
return ret;
}
# 1.3 任何一个async函数都会隐式返回一个promise 我们可以使用then 进行链式编程
queryData().then(function(data){
console.log(data)
})
#2. async 函数处理多个异步函数
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
# 2.1 添加await之后 当前的await 返回结果之后才会执行后面的代码
var info = await axios.get('async1');
#2.2 让异步代码看起来、表现起来更像同步代码
var ret = await axios.get('async2?info=' + info.data);
return ret.data;
}
queryData().then(function(data){
console.log(data)
})
**v-router ** --包含嵌套路由
1.引入相关的库文件
2.添加路由链接
3.添加路由占位符(填充位)
4.创建路由组件
5.配置路由规则并创建路由实例
6.挂载路由实例对象
<script src="./lib/vue_2.5.22.js">script>
<script src="./lib/vue-router_3.0.2.js">script>
<div id="app">
<router-link to="/user">Userrouter-link>
<router-link to="/register">Registerrouter-link>
<router-view>router-view>
div>
<script>
// 4.创建路由组件
const User = {
template: 'User 组件
'
}
//嵌套路由模板
const Register = {
template: `
Register 组件
tab1
tab2
`
}
const Tab1 = {
template: 'tab1 子组件
'
}
const Tab2 = {
template: 'tab2 子组件
'
}
// 5.配置路由规则并创建路由实例
const router = new VueRouter({
// routes 是路由规则数组
routes: [{
//每个路由规则都是一个配置对象,其中至少包含 path 和 component 两个属性
path: '/user',
component: User
}, {
path: '/register',
component: Register,
//嵌套路由--通过chrldren 属性,为 /register 添加子路由规则
children: [{
path: '/register/tab1',
component: Tab1
}, {
path: '/register/tab2',
component: Tab2
}]
}, {
//redirect 表示将要被重定向的新地址
path: '/',
redirect: '/user'
}]
})
const vm = new new Vue({
el: '#app',
data: {},
// 6.挂载路由实例对象
// router: router
router
})
script>
动态路由
<router-link to="/user/1">User1</router-link>
const User = {
props: ['id', 'uname', 'age'], //使用proos接收路由参数
template: ' 用户id为:{{id}}--姓名为:{{uname}}--年龄为:{{age}}'
}
// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [{
path: '/',
redirect: '/user/1'
}, {
path: '/user/:id',
component: User,
//如果 props 被设置为true, route.params 将会被设置为组件属性
// props: true
// props: { uname: 'lisi',age: 20}
//如果要传递id值 props的值应为函数类型
props: route => ({
uname: 'lisi',
age: 20,
id: route.params.id
})
}]
})
命名路由
在配置路由规则并创建路由实例时,添加 name 属性来进行命名
<!-- 使用命名路由 -->
<router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [{
// 命名路由
name: 'user',
path: '/user/:id',
component: User,
props: route => ({
uname: 'zs',
age: 20,
id: route.params.id
})
}]
})
编程式导航
//跳转
this.$router.push('/register')
//后退
this.$router.go(-1)
webpack
1.基本使用步骤
①新建项目空白目录,并运行npm init -y
命令,初始化包管理配置文件package.json
②新建 src 源代码目录
③新建 src-> index.html 首页
④初始化首页基本的结构
⑤运行 npminstall jquery -S
命令,安装jQuery
2.在项目中安装和配置webpack
①运行 npminstall webpack webpack-cli -D
命令,安装webpack 相关的包
②在项目根目录中,创建名为webpack.config.js 的 webpack 配置文件
③在 webpack 的配置文件中,初始化如下基本配置:
module.exports = {
//编译模式
mode: 'development' //两种模式 development production
}
④ 在 package.json 配置文件中的scripts节点下,新增dev脚本如下:
"scripts": {
"dev": "webpack" // script 节点下的脚本,可以通过 npm run 名字 执行
}
⑤ 在终端中运行npm run dev
命令,启动webpack 进行项目打包。
打包的入口文件为 src -> index.js
打包的输出文件为 dist-> main.js
3.配置打包的入口与出口
如果要修改打包的入口与出口,可以在 webpack.config.js 中新增如下配置信息:
const path = require('path')
module.exports = {
entry: path.join(__dirname, './src/index.js'), //打包入口文件的路径
output: {
path: path.join(__dirname, './dist'), // 输出文件的存放路径
filename: 'bundle.js' // 输出文件的名称
}
}
4.配置 webpack 的自动打包功能
1.运行 npm install webpack-dev-server -D
命令,安装支持项目自动打包的工具
2.修改 package.json -> scripts 中的 dev 命令如下:
"scripts": {
"dev": "webpack-dev-server" // script 节点下的脚本,可以通过 npm run 名字 执行
}
3.将 src -> index.html 中, script 脚本的引用路径, 修改为 “/buldle.js”
4.运行 npm run dev
命令, 重新进行打包
5.在浏览器中访问 http://localhost:8080 地址, 查看自动打包效果
注意:
webpack-dev-server会启动一个实时打包的http服务器
webpack-dev-server打包生成的输出文件,默认放到了项目根目录中,而且是虚拟的、看不见的
5.配置 html-webpack-plugin 生成预览页面
1.运行 npm install html-webpack-plugin -D
命令, 安装生成预览页面的插件
2.修改 webpack.config.js 文件头部区域, 添加如下配置信息:
//导入生成预览页面的插件,得到一个构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlguin = new HtmlWebpackPlugin({ //创建插件的实例对象
template: './src/index.html', //指定要用到的模板文件
filename: 'index.html' //指定生成的文件的名称,该文件存在于内存中,在目录中不显示
})
3.修改 webpack.config.js 文件向外暴露的配置对象, 新增如下配置节点:
module.exports = {
plugins: [htmlPlguin], //plugins数组是 webpack 打包期间会用到的一些插件列表
}
6.配置自动打包相关参数
//package.json中的配置
// --open 打包完成后自动打开浏览器
// -- host 配置IP地址
// --port 配置端口
"scripts": {
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888" // script 节点下的脚本,可以通过 npm run 名字 执行
}
webpack加载器 --通过loader打包非js模块
1.打包处理css文件
1.运行 npm install style-loader css-loader -D
安装处理css文件的loader
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.css$/, use: ['style-loader', 'css-loader'} ]
}
2.打包处理less文件
1.运行 npm install less-loader less -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] } ]
}
3.打包处理scss文件
1.运行 npm install sass-loader node-sass -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] } ]
}
4.配置postCss自动添加css的兼容前缀
1.运行 npm install postcss-loader autoprefixer -D
2.在项目根目录中创建 postcss 的配置文件, postcss.config.js, 并初始化如下配置:
const autoprefixer = require('autoprefixer')
module.exports = {
plugins: [autoprefixer] //挂载插件
}
3.在 webpack.config.js 的module -> rules 数组中, 修改css的 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] } ]
}
5.打包样式表中的图片和字体文件
1.运行 npm install url-loader file-loader -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/, use: 'url-loader?limit=16941' } ]
}
其中 ? 之后的是 loader的参数项
limit用来指定图片的大小,单位是字节(byte),只有小于 limit大小的图片,才会被转为base64图片
6.打包处理js文件中的高级语法
1.安装babel转换器相关的包: npm install babel-loader @babel/core @babel/runtime -D
2.安装babel语法插件相关的包: npm install @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties -D
3.在项目根目录中, 创建 babel 配置文件 babel.config.js 并初始化基本配置如下:
module.exports = {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime', '@babel/plugin-proposal-class-properties']
}
4.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//exclude为排除项,表示 babel-loader 不需要处理的js文件
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ } ]
}
7.配置vue组件加载器
1.运行 npm install vue-loader vue-template-compiler -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 vue-loader 的配置如下:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
//plugins数组是 webpack 打包期间会用到的一些插件列表
plugins: [htmlPlguin, new VueLoaderPlugin()],
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.vue$/, use: 'vue-loader' }
]
}
}
8.在webpack项目中使用vue
1.运行 npm install vue -S
安装vue
2.在 src -> index.js 入口文件中, 通过 import Vue from ‘vue’ 来导入 vue 构造函数
3.创建 vue 的实例对象, 并指定要控制的 el 区域
4.通过 render 函数渲染App 根组件
// 1.导入 Vue 构造函数
import Vue from 'vue'
// 2.导入单App根组件
import App from './components/App.vue'
const vm = new Vue({
// 3.指定 vm 实例要控制的页面区域
el: '#app',
// 4.通过 render 函数, 把指定的组件渲染到 el 区域中
render: h => h(App)
})
9.webpack 打包发布
上线之前需要通过webpack将应用进行整体打包,可以通过 package.json 文件配置打包命令:
//在package.json文件中配置 webpack 打包命令
//该命令默认加载项目根目录中的 webpack.config.js 配置文件
"scripts": {
//用于开发调试的命令
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888",
//用于打包的命令
"build": "webpack -p"
}
Vue 脚手架用于快速生成 Vue 项目基础架构,其官网地址为:https://cli.vuejs.org/zh/
安装3.x版本的Vue脚手架: npm install -g @vue/cli
基于3.x版本的脚手架创建vue项目
//1.基于 交互命令行 的方式,创建新版vue项目
vue create 项目名(自定义)
//2.基于 图形化界面 的方式,创建新版vue项目
vue ui
//3.基于 2.x 的旧模板,创建旧版vue项目
npm install -g @vue/cli-init
vue init webpack my-project
Vue脚手架自定义配置
1.在项目的根目录创建文件 vue.config.js
2.在该文件中进行相关配置,从而覆盖默认配置
//vue.config.js
module.exports = {
devServer: {
// 自动打开浏览器
open: true,
//配置默认端口号
port: 8878
}
}
Element-UI
官网为: https://element.eleme.cn/#/zh-CN --桌面端组件库
1.基于命令行方式手动安装
1.安装依赖包 npm install element-ui -S
2.导入 Element-UI 相关资源
//手动配置 element-ui
//导入组件库
import ElementUI from 'element-ui'
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置 Vue 插件
Vue.use(ElementUI)
2.基于图形化界面自动安装
1.运行 vue ui
打开图形化界面
2.通过Vue项目管理器,进入具体的项目配置面板
3.点击 插件 -> 添加插件,进入插件查询面板
4.搜索 vue-cli-plugin-element 并安装
5.配置插件,实现按需导入,从而减少打包后项目的体积
树形表格插件 --vue-table-with-tree-grid
//在main.js中
import TreeTable from 'vue-table-with-tree-grid'
Vue.component('tree-table', TreeTable)
富文本编辑器插件 --vue-quill-editor
//在main.js中
//导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
//导入富文本编辑器对应的样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//将富文本编辑器注册为全局可用组件
Vue.use(VueQuillEditor)
统计图插件 --echarts
//1.导入 echarts
import echarts from 'echarts'
<!-- 2.为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 700px;height:400px;"></div>
// 3.基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 4.指定图表的配置项和数据
const result = _.merge(res.data, this.options)
//5.展示数据
myChart.setOption(result)
深拷贝插件 --lodash
import _ from 'lodash'
_.merge(res.data, this.options)
进度条插件 --nprogerss
//在main.js中
//导入进度条对应的js和css
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
//在request拦截器中,展示进度条 NProgress.start()
axios.interceptors.request.use(config => {
NProgress.start()
config.headers.Authorization = window.sessionStorage.getItem('token')
// 在最后必须 return config
return config
})
//在response拦截器中,隐藏进度条 NProgress.done()
axios.interceptors.response.use(config => {
NProgress.done()
return config
})
去除console插件 --balel-plugin-transform-remove-console
//在babel.config.js文件里的中
//这是项目发布阶段需要用到的babel插件
const prodPlugins = []
if (process.NODE_ENV === 'production') {
prodPlugins.push('transform-remove-console')
}
//"plugins"数组中,插入
...prodPlugins
修改webpack的默认配置
默认情况下,vue-cli 3.0生成的项目,隐藏了webpack配置项,如果我们需要配置webpack
需要通过vue.config.js来配置。
在项目根目录中创建vue.config.js文件,
module.exports = {
chainWebpack:config=>{
//发布模式
config.when(process.env.NODE_ENV === 'production',config=>{
//entry找到默认的打包入口,调用clear则是删除默认的打包入口
//add添加新的打包入口
config.entry('app').clear().add('./src/main-prod.js')
})
//开发模式
config.when(process.env.NODE_ENV === 'development',config=>{
config.entry('app').clear().add('./src/main-dev.js')
})
}
}
补充:
chainWebpack可以通过链式编程的形式,修改webpack配置
configureWebpack可以通过操作对象的形式,修改webpack配置
通过externals加载外部CND资源
//在vue.config.js文件中,放在chainWebpack开发者模式中
config.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
lodash: '_',
echarts: 'echarts',
nprogress: 'NProgress',
'vue-quill-editor': 'VueQuillEditor'
})
})
//然后在index.html的头部区域中,通过CDN加载js和css样式
<% if(htmlWebpackPlugin.options.isProd){ %>
<link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js">script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js">script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js">script>
<script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js">script>
<script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js">script>
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js">script>
<script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js">script>
<% } %>
通过CDN优化ElementUI的打包
1.在main-prod.js中,注释掉element-ui按需加载的代码
2.在index.html的头部区域中,通过CDN加载element-ui的js和css样式
<link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
<script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js">script>
路由懒加载
1.安装 @babel/plugin-syntax-dynamic-import
2.在babel.config.js配置文件中声明该插件
//在"plugins"数组中
'@babel/plugin-syntax-dynamic-import'
3.将路由改为按需加载的形式
//注:webpackChunkName后面为分组名字,最后面是该组件路径
// import Cate from './components/goods/Cate.vue'
const Cate = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Cate.vue')
// import Params from './components/goods/Params.vue'
const Params = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Params.vue')
项目上线配置
1.创建一个新文件夹 运行 npm init -y
初始化
2.运行 npm install express
3.把build的dist文件夹复制到该文件夹内
4.创建app.js入口文件, 配置如下: 然后用node服务器运行该入口文件
const express = require('express')
const app = express()
app.use(express.static('./dist'))
app.listen(80, () => {
console.log('server running at http://127.0.0.1');
})
5.开启gzip配置运行 npm install compression -D
//在app.js中
//网络传输压缩
const compression = require('compression')
//这行代码一定要写到静态资源托管之前
app.use(compression())
6.使用pm2管理应用,安装 npm install pm2 -g
使用pm2启动项目,在终端中输入命令:pm2 start app.js --name 自定义名称
查看项目列表命令:pm2 ls
重启项目:pm2 restart 自定义名称
停止项目:pm2 stop 自定义名称
删除项目:pm2 delete 自定义名称
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
使用Vuex管理数据的好处:
A.能够在vuex中集中管理共享的数据,便于开发和后期进行维护
B.能够高效的实现组件之间的数据共享,提高开发效率
C.存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
使用Vuex管理数据的好处:
A.能够在vuex中集中管理共享的数据,便于开发和后期进行维护
B.能够高效的实现组件之间的数据共享,提高开发效率
C.存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新
Vuex基本使用
1.安装 npm install vuex --save
2.导入vuex包
//在store文件夹或者store.js中
import Vuex from 'vuex'
Vue.use(Vuex)
3.创建store对象
//在store文件夹或者store.js中
const store = new Vuex.Store({
//state 中存放的就是全局共享的数据
state: { count:0 }
})
4.将store对象挂载到vue实例中
new Vue({
el:'#app',
render:h => h(app),
router,
//将创建的共享数据对象,挂载到Vue实例中
//所有的组件,就可以直接从store 中获取全局的数据了
store
})
组件访问State数据
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
方法一: this.$store.state.数据名
--在< template >中可省略 this.
方法二:
<h3>当前最新的count值为:{{count}}</h3>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count'])
}
}
</script>
Mutation
Mutation用于修改变更$store中的数据,并且只能通过mutation变更Store数据,不可以直接操作Store中的数据
使用方法一:
//在store.js
mutations: {
add(state,step){
//第一个形参永远都是state也就是$state对象
//第二个形参是调用add时传递的参数
state.count+=step;
}
}
//在调用的文件中
methods:{
Add(){
//使用commit函数调用mutations中的对应函数,
//第一个参数就是我们要调用的mutations中的函数名
//第二个参数就是传递给add函数的参数
this.$store.commit('add',10)
}
}
使用方法二:
<button @click='sub(10)'>-1</button>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
//获得mapMutations映射的sub函数
...mapMutations(['sub'])
}
}
</script>
Action
在mutations中不能编写异步的代码,会导致vue调试器的显示出错。
在vuex中我们可以使用Action来执行异步操作。
方法一:
//在store.js中
mutations: {
jia (state) {
//变更状态
state.count += 1
}
},
actions: {
//来执行异步操作,不能直接修改state中的数据
addAsync (context) {//若传递有参数 (context, nn)
setTimeout(() => {
context.commit('jia')
}, 1000)
}
//在要使用的文件的methods方法中定义,然后调用dome1函数即可
dome1() {
this.$store.dispatch('addAsync')//若传递有参数 ('addAsync',5)
}
方法二:
//在store.js中同上
<button @click='调用的函数名'>-1</button>
//在要使用的文件的methods方法中
import {mapActions} from 'vuex'
methods:{
...mapActions(['调用的函数名'])
}
Getter
Getter用于对Store中的数据进行加工处理形成新的数据
它只会包装Store中保存的数据,并不会修改Store中保存的数据,当Store中的数据发生变化时,Getter生成的内容也会随之变化
使用方法一: this.$store.getters.名称
使用方法二:
import { mapGetters } from 'vuex'
computed:{
...mapGetters(['调用名称'])
}