Vue
vue概述
渐进式JavaScript框架
声明式渲染–>组件系统–>客户端路由–>集中式状态管理–>项目搭建
官网:https://cn.vuejs.org/v2/guide/
vue基本使用
1.需要提供标签用于填充数据
2.引入vue.js库文件
3.可以使用vue的语法做功能了
4.把vue提供的数据填充到标签里面
实例参数分析:
el:元素的挂载位置(值可以是css选择器或者DOM元素)
data:模拟数据(值是一个对象)
methods:定义方法函数
插值表达式用法:
将数据填充到HTML标签中
插值表达式支持基本的计算操作
vue代码运行原理分析:
概述编程过程的概念(vue语法–>原生语法)
vue模板语法
概述:
前端渲染方式
原生js拼接字符串
使用前端模板引擎
使用vue特有的模板语法
模板语法概览
差值表达式
指令
概念:本质就是自定义属性
格式:以v-开始(比如:v-cloak)
v-cloak指令用法
插值表达式存在的问题:“闪动”
使用v-cloak指令 原理是 先隐藏,替换好值之后再显示最终的值
数据绑定指令
v-text 填充纯文本
v-html 填充HTML片段
v-pre 填充原始信息
数据响应式
概念:数据的变化导致页面内容的变化
数据绑定:将数据填充到标签中
v-once 只编译一次 显示内容后不再具有响应式功能
双向数据绑定
v-model 指令用法:
<input type="text" v-model="uname"/>
事件绑定
v-on指令用法
<input type="button" v-on:click='num++'/>
v-on简写形式
<input type="button" @click='num++'/>
函数事件的调用方式
直接绑定函数名称
<button v-on:click='say'>hello</button>
调用函数
<button v-on:click='say()'>say hi</button>
事件函数参数传递
普通参数和事件对象
<button v-on:click='say("hi",$event)'>Say hi</button>
1.如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数
2.如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
事件修饰符
.stop 阻止冒泡
.prevent 阻止默认行为
按键修饰符
.enter 回车键
<input v-on:keyup.enter='submit'>
.delete 删除键
<input v-on:keyup.delete='handle'>
自定义按键修饰符
全局config.keyCodes对象
Vue.config.keyCodes.f1 = 112
自定义按键修饰符名字是自定义的,但是对应的值必须是按键对应event.keyCode值
属性绑定
v-bind 指令用法
<a v-bind:href='url'>跳转</a>
缩写形式
<a :href='url'>跳转</a>
v-model得底层实现原理分析
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
样式绑定
class样式处理
<div v-bind:class="{ active: isActive }"></div>
数组语法
`<div v-bind:class="[aciveClass, errorClass]"></div>`
1.对象绑定和数组绑定可以结合使用
2.class绑定得值可以简化操作
3.默认得class会保留
style样式处理
对象语法
<div v-bind:style="{ color: activeColor,fontSize: fontSize}"></div>
数组语法
<div v-bind:style="]baseStyles, overrideingStyles"></div>
分支循环结构
分支结构
v-if
v-else
v-else-if
v-show
v-if与v-show的区别
v-if控制元素是否渲染到页面
v-show控制元素是否显示(已经渲染到了页面)
循环结构
v-for遍历数组
`<li v-for='item in list'>{{item}}</li>`
`<li v-for='(item,index) in list'>{{item}} + '---' +{{index}}</li> `
`<div v-for='(value,key,index) in object'></div>`
v-if 和 v-for结合使用
<div v-if='value==12' v-for='(value,key,index) in object'></div>
key的作用:帮助Vue区分不同的元素,从而提高性能
<li :key='item.id' v-for='(item,index) in list'>{{item}} + '---' {{index}}</li>
Vue常用特性
表单操作
表单域修饰符
number:转化为数值
trim:去掉开始和结尾的空格
tazy:将input事件切换为xhange事件
<input v-model.number="age" type="number">
自定义指令
语法:
`Vue.directive('focus', {inserted:function(el) { `
`//获取元素的焦点 `
`el.focus();`
`}})`
用法:
<input type="text" v-focus>
带参数的自定义指令(改变元素的背景色)
`Vue.directive('color',{`
`inserted: function(el, binding) {`
`el.style.backgroundColor = binding.value.color;}`
`})`
指令的用法:
<input type="text" v-color='{color:"orange"}'>
局部指令
`directives: {`
` focus: {`
` //指令的定义`
` inserted: function (el) {`
` el.focus()`
`}}}`
计算属性
表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁
用法:
`computed: {`
`reversedMesssage: function () {`
`return this.msg.split('').reverse().join('')`
`}}`
计算属性与方法的区别
1.计算属性是基于它们的依赖进行缓存的
2.方法不存在缓存
过滤器
作用:格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等
Vue.filter('过滤器名称', function(value){
//过滤业务逻辑
})
过滤器的使用
<div>
{{msg | upper}}
</div>
<div>
{{msg | upper | lower}}
</div>
<div v-bind:id="id | formatId">
</div>
局部过滤器
filters: {
capitalize: function(){}
}
带参数的过滤器
Vue.filter('format', function(value,argl){
//value就是过滤器传递过来的参数
})
侦听器
数据变化时执行异步或开销较大的操作
用法:
watch: {
firstName: function(val){
//val表示变化之后的值
this.fullName = val + this.lastName;
},
lastName: funcion(val) {
this.fullName = this.firstName + val;
}
}
生命周期
主要阶段
1.挂载(初始化相关属性)
beforeCreate
在实例初始化之后,数据观测和事件匹配之前被调用
created
在实例创建完成后被立即调用
beforeMount
在挂载开始之前被调用
mounted
el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子
2.更新(元素或组件的变更操作)
beforeUpdate
数据更新时调用,发生在虚拟DOM打补丁之前
updated
由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
3.销毁(销毁相关属性)
beforeDestroy
实例销毁之前调用
destroyed
实例销毁之后调用
补充
变异方法(修改原有数据)
push() pop() shift() unshift() splice() sort() reverse()
替换数组(生成新的数组)
filter() concat() slice()
修改响应式数据
Vue.set(vm.items,indexOfltem,newValue)
vm.$set(vm.items,indexofltem,newValue)
参数一表示要处理的数组的名称
参数二表示要处理的数组的索引
参数三表示要处理的数组的值
图书管理案例
常用特性应用场景
过滤器(格式化日期)
自定义指令(获取表单焦点)
计算属性(统计图书数量)
侦听器(验证图书存在性)
生命周期(图书数据处理)
vue组件化开发
组件化思想的体现
标准 分治 重用 组合
组件化规范:Web Components
我们希望尽可能多的重用代码
自定义组件的方式不太容易
多次使用组件可能导致冲突
Web Components通过创建分装好功能的定制元素解决上述问题
组件注册
Vue.comonent(组件名称, {
data:组件数据,
template:组件模板内容
})
//定义一个名为button-counter的新组件
Vue.component('button-counter',{
data:function(){
return {
count:0
}
},
template:'<button v-on:click="count++">点击了{{count}}次.</button>'
})
组件用法
<div id="app">
<button-counter></button-counter>
</div>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
组件注册注意事项
1.data必须是一个函数
分析函数与普通对象的对比
2.组件模板内容必须是单个跟元素
分析演示实际的效果
3.组件模板内容可以是模板字符串
模板字符串需要浏览器提供支持
4.组件的命名方式
短横线式 驼峰式
如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
局部组件注册
var ComponentA = {/*...*/}
var ComponentB = {/*...*/}
var ComponentC = {/*...*/}
new Vue({
el:'#app'
components: {
'component-a': ComponentA,
'component-b': ComponentB,
'component-c': ComponentC,
}
})
Vue调试工具
工具安装
1.克隆仓库
2.安装依赖包
3.构建
4.打开Chrome扩展页面
5.选中开发者模式
6.加载已解压的扩展,选择shells/chrome
组件间数据交互
父组件向子组件传值
1.组件内部通过props接受传递过来的值
Vue.component('menu-item', {
props: {'title'},
template: '<div>{{title}}</div>'
})
2.父组件通过属性将值传递给子组件
<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>
3.props属性名规则
在props中使用驼峰形式,模板中需要使用短横线的形式
字符串形式的模板中没有这个限制
Vue.component('menu-item', {
//在javaScript中是驼峰式的
props: {'menuTitle'},
template: '<div>{{menuTitle}}</div>'
})
<--在html中是短横线方式的-->
<menu-item menu-title="nihao"></menu-item>
4.props属性值类型
字符串String
数值Number
布尔型Boolean
数组Array
对象Object
子组件向父组件传值
1.子组件通过自定义事件向父组件传递信息
<button v-on:click='$emit("enlarge-text")'>
扩大字体
</button>
2.父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
3.子组件通过自定义事件向父组件传递信息
<button v-on:click='$emit("enlarge-text",0.1)'>
扩大字体
</button>
4.父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize += $event'></menu-item>
非子父组件间传值
单独的事件中心管理组件间的通信
var eventHub = new Vue()
监听事件与销毁事件
eventHub.$on('add-todo',addTodo)
eventHub.$off('add-todo')
触发事件
eventHub.$emit('add-todo',id)
组件插槽
作用:
父组件向子组件传递内容
1.插槽位置
Vue.component('alert-box', {
template:'
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
'
})
2,插槽内容
<alert-box>Something bad happened.</alert-box>
3.具名插槽用法
插槽定义
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
插槽内容
<base-layout>
<h1 slot="header">
标题内容
</h1>
<p>
主要内容
</p>
<p>
主要内容
</p>
<p slot="footer">
底部内容
</p>
</base-layout>
4.作用域插槽
应用场景:父组件对子组件的内容进行加工处理
插槽定义:
<ul>
<li v-for="item in list" v-bind:key="item.id">
<slot v-bind:item="item">
{{item.name}}
</slot>
</li>
</ul>
插槽内容:
<fruit-list v-bind:list="list">
<template slot-scope="slotProps">
<strong v-if="slotProps.item.current"> {{slotProps.item.text}}
</strong>
</template>
</fruit-list>
前后交互
前后端交互模式
接口调用方式:
原生ajax , fetch , axios
Promise用法:
异步调用
定时任务
Ajax
事件函数
多次一部调用的依赖分析:
多次异步调用的结果顺序不确定
异步调用结果如果存在依赖需要嵌套
$.ajax({
success:function(data){
if(data.status == 200){
$.ajax({
success:.function(data){
if(data.status == 200){
$.ajax({
success.function(data){
if(data.status == 200){}
}
})
}
}
})
}
}
})
Promise用法
概述:
promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获得异步操作的消息
使用其有以下好处:
1.可以避免多层异步调用嵌套问题(回调地狱)
2.Promise对象提供了简洁的API,使得控制异步操作更加容易
官网:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Promise
Promise基本用法:
实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务
resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果
var p = new Promise(function(resolve,reject){
//成功时调用resolve()
//失败时调用reject()
});
p.then(function(ret){
//从resolve得到正常结果
},function(ret){
//从reject得到错误信息
});
基于Promise处理Ajax请求
处理原生
function queryData(){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.status == 200){
reslove(xhr.responseText)
}else{{
reject('出错了');
}
}
xhr.open('get','/data');
xhr.send(null);
})
}
发送多次ajax请求
queryData()
.then(function(data){
return queryData();
})
.then(function(data){
return queryData();
})
.then(function(data){
return queryData();
});
then参数中的函数返回值
1.返回Promise实例对象
返回的该实例对象会调用下一个then
2.返回普通值
返回的普通值会直接传递给下一个then,通过then参数中函数接受该值
Promise常用的API
1.实例方法
p.then() 得到异步任务的正确结果
p.catch() 获取异常信息
p.finally() 成功与否都会执行(尚且不是正式标准)
queryData()
.then(function(data){
console.log(data);
})
.catch(function(data){
console.log(data);
})
.finally(function(){
console.log('finished');
});
2.对象方法
Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.all([p1,p2,p3]).then((result) => {
console.log(result)
})
Promise.race([p1,p2,p3]).then((result) => {
console.log(result)
})
接口调用-fetch用法
更加简单的数据获取方式,功能更加强大,更灵活,可以看作事xhr的升级版
基于Promise实现
fetch(url).then(fn2)
.then(fn3)
...
.catch(fn)
官网:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
fetch的基本用法
fetch('/abc').then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
});
fetch请求参数
常用配置选项
method(String):HTTP请求方法,默认为GET(GET,POST,PUT,DELETE)
body(String):HTTP的请求参数
headers(Object):HTTP的请求头,默认为{}
fetch('/abc',{
method:'get'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
});
2.GET请求方式的参数传递
fetch('/abc?id=123').then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
});
fetch('/abc/123',{
method:'get'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
});
3.DELETE请求方式的参数传递
fetch('/abc/123',{
method:'delete'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
});
4.POST请求方式的参数传递
fetch('/books',{
method:'post',
body:'uname=listi&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded',
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
});
fetch('/books',{
method:'post',
body:JSON.stringify({
uname:'list',
age:12
})
headers:{
'Content-Type':'application/json',
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
});
5.PUT请求方式的参数传递
fetch('/books/123',{
method:'put',
body:JSON。stringify({
uname:'list',
age:12
})
headers:{
'Content-Type':'application/json',
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
});
fetch响应结果
响应数据格式
text() :将返回体处理成字符串类型
json() : 返回结果和JSON.parse(responseText)一样
fetch('/abc'then(data=>{
//return data.text();
return data.json();
}).then(ret=>{
console.log(ret);
});
接口调用-axios用法
axios的基本特性
官网:https://github.com/axios/axios
axios是一个基于Promise用于浏览器和node.js的HTTP客户端
它具有如下特性:
1.支持浏览器和node.js
2.支持promise
3.能拦截请求和响应
4.自动转换JSON数据
axios.get('/adata')
.then(ret=>{
//data属性名称是固定的,用于获取后台响应数据
console.log(ret.data)
})
axios的常用API
get:查询数据
post:添加数据
put:修改数据
delete:删除数据
axios的参数传递
GET传递参数
通过URL传递参数
通过params选项传递参数
axios.get('/adata?id=123')
.then(ret=>{
console.log(ret.data)
})
axios.get('/adata/123')
.then(ret=>{
console.log(ret.data)
})
axios.get('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data)
})
DELETE传递参数
参数传递方式于GET类似
axios.delete('/adata?id=123')
.then(ret=>{
console.log(ret.data )
})
axios.delete('/adata/123')
.then(ret=>{
console.log(ret.data)
})
axios.delete('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data)
})
POST传递参数
通过选项传递参数(默认传递的是json格式的数据)
axios.post('/adata',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
通过URLSearchParams传递参数(applikcation/x-www-form-urlencoded)
const params = new URLSearchParams();
params.append('param1','value1');
params.append('param2','value2');
axios.post('/api/test',params).then(ret=>{
console.log(ret.data)
})
PUT传递参数
参数传递方式与POST类似
axios.put('/adata/123',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
axios的响应结果
响应结果的主要属性
data:实际响应回来的数据
headers:响应头信息
status:响应状态码
statusText:响应状态信息
axios.post('/axios-json').then(ret=>{
console.log(ret)
})
axios的全局配置
axios.defaults.timeout = 3000; //超时时间
axios.defaults.baseURL = ‘http://localhost:3000/app’; //默认地址
axios.defaults.headers[‘mytoken’] = ‘apwerwqwerqwer23eresdf23’ //设置请求头
axios拦截器
请求拦截器
在请求发出之前设置一些信息
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些信息设置
return config;
},function(err){
//处理响应的错误信息
});
响应拦截器
在获取数据之前对数据做一些加工处理
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在这里对返回的数据进行处理
return res;
},function(err){
//处理响应的错误信息
})
接口调用-async/await用法(重点)
async/await的基本用法
async/await是ES7引入的新语法,可以更加方便的进行异步操作
async关键子用于函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(id){
const ret = await axios.get('/data');
return ret;
}
queryData.then(ret=>{
console.log(ret)
})
async/await处理多个异步请求
async function queryData(id){
const info = await axios.get('/asyncl');
const ret = await axios.get('async2?info='+info.data);
return ret;
}
queryData.then(ret=>{
console.log(ret)
})
前端路由
路由:路由的本质就是对应关系
后端路由:根据不同用户的URL请求,返回不同的内容,本质就是URL地址与服务器之间的对应关系
前端路由:根据不同的用户事件,显示不同的页面内容,本质就是用户事件处理函数之间的对应关系
实现简单的前端路由
//监听window的onhashchange事件,过呢据获取到的最新的hash值,切换要显示的组件的名称
window.onhashchange = function(){
//通过location.hash获取到最新的hash值
}
Vue Router
官网:https://router.vuejs.org/zh/ 是vue.js官方的路由管理器它和Vue.js的核心深度集成,可以非常方便的用于SPA应用程序的开发
Vue Router包含的功能:
1.支持HTMLS历史模式或hash模式
2.支持嵌套路由
3.支持路由参数
4.支持编程式路由
5.支持命名路由
Vue rRouter 的基本使用
引入相关的库文件
<!--导入vue文件,为全局window对象挂载Vue构造函数-->
<script src="./lib/vue_2.5.22.js"></script>
<!--导入vue-router文件,为全局window对象挂载VueRouter构造函数-->
<script src="./lib/vue-router_3.0.2.js"></script>
添加路由链接
<!--router-link 是 vue中提供的标签,默认会被渲染为a标签-->
<!--to 属性默认会被渲染为href属性-->
<!--to 属性的值默认会被渲染为#开头的hash地址-->
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
添加路由填充位
<!--路由填充位(也叫作路由占位符) -->
<!--将来通过路由规则匹配到的组件,将会被渲染到 router-view 所在的位置-->
<router-view></router-view>
配置路由规则并创建路由实例
//创建路由实例对象
var router = new VueTouter({
//router是路由规则数组
router:[
//每一个路由规则都是一个配置对象,其中至少包含hash 和 component两个属性:
//path表示当前路由规则匹配的hash地址
//component表示当前路由规则对应要展示的组件
{path:'/user',component:User},
{path:'/register',component:Register}
]
})
把路由挂载到Vue根实例中
new Vue({
el:'#app',
//为了能够让路由规则生效,必须把路由对象挂载到vue实例对象上
router //router:router
});
路由重定向
路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面;
通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由地重定向;
var router = new VueRouter({
routers: [
//其中,path表示需要被重定向地原地址,redirect表示将要被重定向到地新地址
{path:'/',redirect:'/user'},
{path:'/user',componenet:User},
{path:'/register',component:Register}
]
})
vue-router嵌套路由
嵌套路由功能分析:
1.点击父级路由链接显示模板内容
2.模板内容中又有子级路由链接
3.点击子级路由链接显示子级模板内容
嵌套路由用法
父路由组件模板
父级路由链接
父组件路由填充位
<p>
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
</p>
<div>
<!--控制组件的显示位置-->
<router-view></router-view>
</div>
子级路由模板
子级路由链接
子级路由填充位
const Register = {
template:<div>
<h1>Register 组件</h1>
<hr/>
<router-link to="/register/tab1">Tab1</router-link>
<router-link to="/register/tab2">Tab2</router-link>
<!--子路由填充位-->
<router-view/>
</div>
}
嵌套路由配置
父级路由通过children属性配置子级路由
const router = new VueRouter({
routes: [
{path:'/user',component:User},
{
path:'/register',
component:Register,
//通过children属性,为/register添加子路由规划
children: [
{path:'/register/tab1',component:Tab1},
{path:'/register/tab2',component:Tab2}
]
}
]
})
vue-router动态路由匹配
动态匹配路由的基本用法
思考:
<!--有如下3个路由链接-->
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
{path:'/user/1',component:User}
{path:'/user/2',component:User}{path:'/user/3',component:User}
应用场景:通过动态路由参数的模式进行路由匹配
var router = new VueRouter({
routes: [
//动态路径参数 以冒号开头
{path:'/user/:id',component:User}
]
})
const User = {
//路由组件中通过$route.params获取路由参数
template:'<div>User{{$route.params.id}}</div>'
}
路由组件传递参数
$route与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦
1.props的值为布尔类型
const router = new VueRouter({
routes:[
//如果props被设置为true.route.params将会被设置为组件属性
{path:'/user/:id',component:User,props:true}
]
})
const User = {
props:['id'],//使用props接收路由参数
template:'<div>用户ID:{{id}}</div>'//使用路由参数
}
2.props的值为对象类型
const router = new VueRouter({
routes:[
//如果props是一个对象,它会被按原样设置为组件属性
{path:'/user/:id',component:User,props:{uname:'list',age:12}}
]
})
const User = {
props:['uname','age'],
template:'<div>用户信息:{{uname + '----' + age}}</div>'
}
3.props的值为函数类型
const router = new VueRouter({
routes:[
//如果props是一个函数,则这个函数接收route对象为自己的形参
{ path:'/user/:id',
component:User,
props:route => ({uanme:'zs',age:20,id:route.params.id})}
]
})
const User = {
props:['uname','age','id'],
template:'<div>用户信息{{uname + '-----' + 'id'}}</div>'
}
vue-router命名路由
命名路由的配置规则
为了更加方便地表示路由的路径,可以给路由规则起一个别名,即为“命名路由”。
const router = new VueRouter({
routes: [
{
path:'/user/:id',
name:'user',
component:User
}
]
})
<router-link :to="{name:'user',params:{id:123}}">User</router-link>
router.push({name:'user',params:{id:123}})
vue-router编程时导航
页面导航的两种方式
声明式导航:通过点击链接实现导航的方式,叫做声明式导航
例如:普通网页中的链接或者vue中的
编程式导航:通过调用JavaScript形式的API实现导航的方式,叫做编程式导航
例如:普通网页中的location.href
编程式导航基本用法
常用的编程式导航API如下:
this.$router.push(‘hash地址’)
this.$router.go(n)
const User = {
template:'<div><button @click="goRegister">跳转到注册页面<button></div>',
method:{
goRegister:function(){
//用编程的方式控制路由跳转
this.$router.push('/register');
}
}
}
编程式导航参数规则
router.push()方法的参数规则
//字符串(路径名称)
router.push('/home')
//对象
router.push({path:'/home'})
//命名的路由(传递参数)
router.push({name:'/user',params:{userId:123}})
//帮查询参数,变成 /register?uname=lisi
router.push({path:'/register',query:{uname:'lisi'}})
前端工程化
传统开发主要问题:
1.命名冲突 2.文件依赖
通过模块化解决上述问题
模块化就是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块
模块化开发的好处:方便代码的重用,从而提升开发效率,并且方便后期的维护
模块化相关规范
浏览器端模块化规范
1.AMD
Requier.js (http://www.requirejs.cn/)
2.CMD
Sea.js (htttps://seajs.github.io/seajs/docs/)
服务器端模块化规范
1.CommonJS
模块分为单文件和包
模块成员导出:module.exports和exports
模块成员导入:require(‘模块标识符’)
大一统的模块化规范-ES6模块化
在ES6模块化规范诞生之前,Javascript社区已经尝试并提出了AMD,CMD,CommonJS,等模块化规范
但是,这些社区提出的模块化标准,还是存在一定的差异性与局限性,并不是浏览器与服务器通用的模块化标准,例如:
AMD和CMD适用于浏览器端的Javascript模块化
CommonJS适用于服务器的JavaScript模块化
因此,ES6语法规范中,在语言层面上定义了ES6模块化规范,是浏览器端与服务器端通用的模块化开发规范
ES6模块化规范中定义:
每个js文件都是一个独立的模块
导入模块成员使用import关键字
暴露模块成员使用export关键字
Node.js中通过babel体验ES6模块化
1.npm install --save-dev @babel/core @babel/cli @ba el/preset-env @babel/node
2.npm install --save @babel/polyfill
3.项目根目录创建文件babel.config.js
4.babel.config.js文件内容如下代码
const presets = {
["@babel/env",{
targets:{
edge:'17',
firefox:'60',
chrome:'67',
safari:'11.1'
}
}]
};
module.exports = {presets};
ES6模块化的基本语法
默认导出 与 默认导入
默认导出语法 export default默认导出的成员
//当前文件模块为m1.js
//定义私有成员a和c
let a = 10
let c = 20
//外界访问不到变量d,因为它没有被暴露出去
let d = 30
function show(){}
//将本模块中的私有成员暴露出去,供其他模块使用
export default {
a,
c,
show
}
默认导入语法import接收名称from“模块标识符”
//导入模块成员
import m1 from "./m1.js"
console.log(m1)
//打印输出的结果为:
//{a:10,c:20,show:{Function:show}}
注意:每个模块中,只允许使用唯一的一次 export default,否则会报错!
按需导出 与 按需导入
按需导出语法 export let s1 = 10
按需导入语法 import {s1} from ‘模块标识符’
//当前文件模块为m1.js
//向外按需导出变量 s1
export let s1 = "aaa"
//向外按需导出变量 s2
export let s2 = "ccc"
//向外按需导出方法say
export function say = function(){}
//导入模块成员
import {s1,s2 as ss2,say} from './m1.js'
console.log(s1) //打印输出aaa
console.log(ss2) //打印输出ccc
console.log(say) //打印输出{Function:say}
注意:每个模块中,可以使用多次按需导出!
直接导入并执行模块代码
有时候,我们只想单纯执行某个模块中的代码,并不需要得到模块中向外暴露的成员,此时,可以直接导入并执行模块代码
//当前文件模块为m2.js
//在当前模块中执行一个for循环操作
for(let i = 0;i < 3;i++){
console.log(i);
}
//直接导入并执行模块代码
import './m2.js'
webpack
webpack概述
webpack是一个流行的前端项目构建工具(打包工具),可以解决当前web开发中所面临的困境
webpack提供了友好的模块化支持,以及代码压缩混淆,处理js兼容问题,性能优化等强大的功能,从而让程序员把工作的重心放到具体的功能实现上,提供了开发效率和项目的可维护性
目前绝大多数企业中的前端项目,都是基于webpack进行打包构建的
webpack的基本使用
创建列表隔行变色项目
1.新建项目空白目录,并运行npm init -y命令,初始化包管理配置文件package.json
2.新建src源代码目录
3.新建src ->index.html首页
4.初始化首页基本的结构
5.运行npm install jquery -s 命名,安装jQuery
6.通过模块化的形式,实现列表隔行变色效果
在项目中安装和配置webpack
1.运行npm install webpack webpack-cli -D命令,安装webpack相关的包
2.在项目根目录中,创建名为webpack.config.js的webpack配置文件
3.在webpack的配置文件中初始化如下基本配置:
module.export = {
mode:'development' //mode用来指定构建模式
}
4.在package.json配置文件中的scripts节点下,新增dev脚本如下:
"scripts":{
"dev":"webpack" //script节点下的脚本,可以通过npm run 执行
}
5.在终端中运行npm run dev 命令,启动webpack进行项目打包
配置打包的入口与出口
webpack的4.x版本中默认约定:
打包的入口文件为src -> index.js
打包的输出文件为 dist -> main.js
如果要修改打包的入口与出口,可以在webpack.config.js中新增如下配置信息:
const path = require('path') //导入node.js中专门操作路径的模块
module.exports = {
entry:path.join(__dirname,'./src/index.js'),//打包入口文件的路径
output:{
path:path.join(__dirname,'./dist'),//输出文件的存放路径
filename:'bundle.js' //输出文件的名称
}
}
配置webpack的自动打包功能
运行npm install webpack-dev-server -D命令,安装支持项目自动打包的工具
修改package.json -> scripts中的dev命令如下:
"scripts":{
"dev":"webpack-dev-server" //script节点下的脚本,可以通过npm run执行
}
将src -> index.html中,script脚本的引用路径,修改为"/buldle.js"
运行npm run dev 命令,重新进行打包
在浏览器中访问http://localhost:8000 地址,查看自动打包效果
**注意:**webpack-dev-server 会启动一个实时打包的http服务器
webpack-dev-server打包生成的输出文件,默认放到了项目根目录中,而且是虚拟的,看不见的
配置html-webpack-plugin生成预览页面
运行npm install html-webpack-plugin -D命令,安装生成预览页面的插件
修改webpack.config.js文件头部区域,添加如下配置信息:
//导入生成预览页面的插件,得到一个构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin({
template:'./src/index.html',//指定要用到的模板文件
filename:'index.html'//指定生成的文件的名称,该文件存在于内存中,在目录中不显示
})
修改webpack.config.js文件中向外暴露的配置对象,新增如下配置节点:
module.exports = {
plugins:[htmlPlugin] //plugins数组是webpack打包期间会用到的一些插件列表
}
配置自动打包相关的参数
//package.json中的配置
//--open打包完成后自动打开浏览器页面
//--host配置IP地址
//--port配置端口
"scripts":{
"dev":"webpack-dev-server --open --host 127.0.0.1 --port 0000"
},
webpack中的加载器
通过loader打包非模块
在实际开发中,webpack默认只能打包处理以 .js后缀名结尾的模块,其他非.js后缀名结尾的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错
loader加载器可以协助webpack打包处理特定的文件模块比如:
1.less-loader可以打包处理.less相关的文件
2.sass-loader可以打包处理。scss相关的文件
3.url-loader可以打包处理css中与url路劲相关的文件
webpack中加载器的基本使用
1.打包处理css文件
运行npm i style-loader css-loader -D命令,安装处理css文件的loader
在webpack.config.js的module ->rules数组中,添加loader规则如下:
//所有第三方文件模块的匹配规则
module:{
rules:{
{text:/\.css$/,use:['style-loader','css-loader']}
}
}
其中,test表示匹配的文件类型,use表示对应要调用的loader
**注意:**use数组中指定的loader顺序是固定的,多个loader的调用是:从后往前调用
打包处理less文件
运行npm i less-loader less -D命令
在webpack.config.js的module -> rules数组中,添加loader规则如下:
//所有第三方文件模块的匹配规则
module:{
rules:{
{test:/\.less$/,use:['style-loader','css-loader','less-loader']}
}
}
打包处理scss文件
运行npm i sass-loader node-scss -D命令
在webpack.config.js的module -> rules数组中,添加loader规则如下:
//所有第三方文件模块的匹配规则
module:{
rules:[
{test:/\.scss$/,use:['style-loader','css-loader','sass-loader']}
]
}
配置postCSS自动添加css的兼容前缀
运行mpm i postcss-loader autoprefixer -D命令
在项目根目录中创建postcss的配置文件postcss.config.js,并初始化如下配置:
const autoprefixer = require('autoprefixer')//导入自动添加前缀的插件
module.exports = {
plugins:[autoprefixer]//挂载插件
}
在webpack.config.js的module -> rules 数组中,修改css的loader规则如下:
module:{
rules:[
{text:/\.css$/,use:['style-loader','css-loader','postcss-loader'}
]
}
打包样式表中的图片和字体文件
运行npm i url-loader file-loader -D命令
在webpack.config.js的module -> rules数组中,添加loader规则如下:
module:{
rules:[
{
test:/\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
use:'url-loader?limit=16940'
}
]
}
其中?之后的是loader的参数项,
limit用来指定图片的大小,单位是字节,只有小于limit大小的图片,才会被转为base64图片
打包处理js文件中的高级语法
1.安装babel转换器相关的包:npm i babel-loader @babel/core @babel/runtime -D
2.安装babel语法插件相关的包:npm i @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规则如下:
//exclude为排除项,表示babel-loader不需要处理node_modules中的js文件
{test:/\.js$/,use:'babel-loader',exclude:/node_modules/}
Vue单文件组件
传统组件问题和解决方案
问题:
1.全局定义的组件必须保证组件的名称不重复
2.字符串模板缺乏语法高亮,在HTML有多行的时候,需要用到""转义
3.不支持CSS意味着当HTML和JavaScript组件化时,CSS明显被遗漏
4.没有构建步骤限制,只能使用HTML和ESS JavaScript,而不能使用预处理器(如:Babel)
解决方案:
针对传统组件的问题,Vue提供了一个解决方案—使用Vue单文件组件
单文件组件的组成结构
template:组件的模板区域**
script:业务逻辑区域
style:样式区域
<template>
<!--这里用于定义Vue组件的模板内容-->
</template>
<script>
//这里用于定义Vue组件的业务逻辑
export default{
data:(){return {}},//私有数据
methods:{}//处理函数
//...其他业务逻辑
}
<script>
<style scoped>
/*这里用于定义组件的样式*/
</style>
webpack中配置vue组件的加载器
1.运行npm i vue-loader vue-template-compiler -D命令
2.在webpack.config.js配置文件中,添加vue-loader的配置项如下:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module:{
rules:[
//...其他规则
{test:/\.vue$/,loader:'vue-loader'}
]
},
plugins:[
//...其他插件
new VueLoaderPlugin()//请确保引入这个插件!
]
}
在webpack项目中使用vue
1.运行npm i 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)
})
webpack打包发布
上线之前需要通过webpack将应用进行整体的打包,可以通过package.json文件配置打包命令:
//在package.json文件中配置webpack打包命令
//该命令默认加载项目根目录中的webpack.config.js配置文件
"scripts":{
//用于打包的命令
"build":"webpack-p",
//用于开发调试的命令
"dev":"webpack-dev-server --open --host 127.0.0.1 --port 3000",
},
Vue脚手架
Vue脚手架的基本用法
Vue脚手架用于快速生成Vue项目基础架构,器官网地址为:https://cli.vuejs.org/zh/
使用步骤
1.安装3.x版本的Vue脚手架:
npm install -g @vue/cli
基于3.x版本的脚手架创建vue项目
//1.基于交互式命令行的方式,创建新版的vue项目
vue create my-project
//2.基于图形化界面的方式,创建新版vue项目
vue ui
//3.基于2.x的旧模板,创建旧办vue项目
npm install -g @vue/cli-init
vue init webpack my-project
//1.基于交互式命令行的方式,创建新版vue项目
vue create my-project
//2.基于图形化界面的方式,创建新版vue项目
vue ui
//3.基于2.x的旧模板,创建旧版vue项目
npm install -g @vue/cli-init
vue init webpack my-project
Vue脚手架生成的项目结构分析
node_modules 依赖包目录
public 静态资源目录
src 组件源码目录
babel.config.js Babel配置文件
Vue脚手架的自定义配置
1.通过package.json配置项目
//必须是符合规范的json语法
"vue":{
"devserver"{
"port":"0000",
"open":true
}
},
注意:不推荐使用这种配置方式,因为package.json主要用来管理包的配置信息;为了方便维护,推荐将vue脚手架相关的配置,单独定义到vue.config.js配置文件中。
2.通过单独的配置文件配置项目
1.在项目的根目录创建文件vue.config.js
2.在该文件中进行相关配置,从而覆盖默认配置
//vue.config.js
module.exports = {
devServer:{
port:0000
}
}
Element-UI的基本使用
Element-UI:一套为开发者,设计师和产品经理准备的基于Vue 2.0的桌面端组件库。
官网地址为:http://element-cn.eleme.io/#/zh-CN
1.基于命令行方式手动安装
1.安装依赖包npm i element-ui -S
2.导入Element-UI相关资源
//导入组件库
import ElementUI from 'element-ui';
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css';
//配置Vue插件
Vue.use(ElementUI);
基于图形化界面自动安装
1.运行vue ui 命令,打开图形化界面
2.通过Vue项目管理器,进入具体的项目配置面板
3.点击插件->添加插件,进入插件查询面板
4.搜索vue-cli-plugin-element并安装
5.配置插件,实现按需导入,从而减少打包后项目的体积
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)
})
webpack打包发布
上线之前需要通过webpack将应用进行整体的打包,可以通过package.json文件配置打包命令:
//在package.json文件中配置webpack打包命令
//该命令默认加载项目根目录中的webpack.config.js配置文件
"scripts":{
//用于打包的命令
"build":"webpack-p",
//用于开发调试的命令
"dev":"webpack-dev-server --open --host 127.0.0.1 --port 3000",
},
Vue脚手架
Vue脚手架的基本用法
Vue脚手架用于快速生成Vue项目基础架构,器官网地址为:https://cli.vuejs.org/zh/
使用步骤
1.安装3.x版本的Vue脚手架:
npm install -g @vue/cli
基于3.x版本的脚手架创建vue项目
//1.基于交互式命令行的方式,创建新版的vue项目
vue create my-project
//2.基于图形化界面的方式,创建新版vue项目
vue ui
//3.基于2.x的旧模板,创建旧办vue项目
npm install -g @vue/cli-init
vue init webpack my-project
//1.基于交互式命令行的方式,创建新版vue项目
vue create my-project
//2.基于图形化界面的方式,创建新版vue项目
vue ui
//3.基于2.x的旧模板,创建旧版vue项目
npm install -g @vue/cli-init
vue init webpack my-project
Vue脚手架生成的项目结构分析
node_modules 依赖包目录
public 静态资源目录
src 组件源码目录
babel.config.js Babel配置文件
Vue脚手架的自定义配置
1.通过package.json配置项目
//必须是符合规范的json语法
"vue":{
"devserver"{
"port":"0000",
"open":true
}
},
注意:不推荐使用这种配置方式,因为package.json主要用来管理包的配置信息;为了方便维护,推荐将vue脚手架相关的配置,单独定义到vue.config.js配置文件中。
2.通过单独的配置文件配置项目
1.在项目的根目录创建文件vue.config.js
2.在该文件中进行相关配置,从而覆盖默认配置
//vue.config.js
module.exports = {
devServer:{
port:0000
}
}
Element-UI的基本使用
Element-UI:一套为开发者,设计师和产品经理准备的基于Vue 2.0的桌面端组件库。
官网地址为:http://element-cn.eleme.io/#/zh-CN
1.基于命令行方式手动安装
1.安装依赖包npm i element-ui -S
2.导入Element-UI相关资源
//导入组件库
import ElementUI from 'element-ui';
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css';
//配置Vue插件
Vue.use(ElementUI);
基于图形化界面自动安装
1.运行vue ui 命令,打开图形化界面
2.通过Vue项目管理器,进入具体的项目配置面板
3.点击插件->添加插件,进入插件查询面板
4.搜索vue-cli-plugin-element并安装
5.配置插件,实现按需导入,从而减少打包后项目的体积