文章目录
vue入门
-
vue引入
下载源码
cdn引入(Content Delivery Network,即内容分发网络) -
hello vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--
MVVM: M(model),V(view),VM(ViewModel)
-->
<!--vue实例控制的这个元素区域就是 MVVM 中的V视图-->
<div class="app">
<p>{{msg}}</p>
</div>
<script>
/**
* 创建view实例
* 导入vue包后,在浏览器内存中就会多一个Vue的构造函数
* 下面new出来的vm对象就是MVVM中的VM调度者
*/
var vm=new Vue({
el: '.app',//vue实例控制页面的哪个区域
data: { //存放el要用到的数据
msg:'hello,vue!'//通过vue提供的指令,很方便的把数据渲染到页面上,程序员不用动手操作DOM元素
}
})
</script>
</body>
</html>
指令
- v-model
在html页面中修改msg内容,会直接修改vue中的msg
<body>
<div id="app">
<p>{{msg}}</p>
<!--v-model 数据双向绑定-->
<input type="text" v-model="msg">
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
</script>
</body>
- v-text
解决{{对象}}闪现的问题
<div id="app">
<p>{{msg}}</p>
<p v-text="msg"></p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
</script>
- v-html
可以执行html命令字符串
<div id="app">
<p>{{msg}}</p>
<p v-html="msg"></p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'<h1>学习vue</h1>'
}
})
</script>
- v-cloak
和css规则[v-cloak]{display:none}一起使用,可以隐藏未编译的Mustache直到实例准备完毕
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<p v-cloak>{{msg}}</p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'学习vue'
}
})
</script>
</body>
</html>
- v-for
<body>
<div id="app">
<!--迭代简单数组-->
<!--<p v-for="(item,i) in list">索引:{{i}} 值:{{item}}</p>-->
<!--迭代复杂数组-->
<!--<p v-for="(item,i) in listC">索引:{{i}} id:{{item.id}} 名字:{{item.name}}</p>-->
<!--迭代对象中的属性-->
<!--<p v-for="(val,key,i) in userInfo">索引:{{i}} 属性值{{val}} 属性名{{key}}</p>-->
<!--迭代数字-->
<p v-for="item in 10">第{{item}}轮循环</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
list: [1, 2, 3, 4, 5, 6, 7],
listC:[
{id:1,name:'张三'},
{id:2,name:'李四'},
{id:3,name:'王五'},
{id:4,name:'陈六'}
],
userInfo:{
id:1,
name:'张三',
gender:'男'
}
}
})
</script>
</body>
注意 在2.2.0+版本中,当使用v-for时,key必须使用
Vue.js中v-for在更新已经渲染过的元素列表时,默认使用“就地复用”策略。为了方便vue能跟踪每个结点的身份,从而重用和重新排序现有元素,我们需要给一个唯一的key属性(key的值必须为string或number类型)
<body>
<div id="app">
<div>
<lable>Id:
<input type="text" v-model="id">
</lable>
<lable>Name:
<input type="text" v-model="name">
</lable>
<input type="button" value="添加" @click="add">
</div>
<div>
<!--key指定可以唯一标识的值-->
<p v-for="item in list" :key="item.id">
<input type="checkbox"> {{item.id}} {{item.name}}
</p>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
id:'',
name:'',
list: [
{id: 1, name: '张三'},
{id: 2, name: '李四'},
{id: 3, name: '王五'},
{id: 4, name: '陈六'}
]
},
methods:{
add(){
/*unshift向数组中队头添加对象*/
this.list.unshift({id:this.id,name:this.name});
}
}
})
</script>
</body>
- v-if和v-show
div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<!--v-if:每次都会重新删除或创建元素-->
<h3 v-if="flag">这是v-if控制的元素</h3>
<!--v-show:每次都不会重新进行DOM的删除和操作,只是切换了元素的display:none样式-->
<h3 v-show="flag">这是v-show控制的元素</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
flag:true
}
})
</script>
绑定样式
元素绑定class样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.red{
color: red;
}
.italic{
font-style: italic;
}
.active{
letter-spacing: 0.5em;
}
</style>
</head>
<body>
<!--<!–html原生的添加class方式–>
<h1 id="h1" class="red italic active">{{msg}}</h1>-->
<!--使用v-bind绑定-->
<!--<h1 id="h1" :class="['red','italic','active']">{{msg}}</h1>-->
<!--将class对应的数组对象提取出来写在vue实例的data中-->
<!--<h1 id="h1" :class="classObj">{{msg}}</h1>-->
<!--使用使用三元表达式-->
<!--<h1 id="h1" :class="['red','italic',flag?'active':'']">{{msg}}</h1>-->
<!--使用对象代替三元表达式-->
<!--<h1 id="h1" :class="['red','italic',{'active':flag}]">{{msg}}</h1>-->
<!--注意
在class中使用v-bind绑定对象时,对象的属性名是类名,由于对象的属性可带引号,也可以不带
-->
<script type="text/javascript">
var vm=new Vue({
el: '#h1',
data:{
msg:'我是一级标题',
flag:false,
classObj:['red','italic','active']
}
})
</script>
</body>
</html>
元素绑定style样式
<body>
<!--直接通过:style方式-->
<!--<h1 id="h1" :style="{color:'red','font-size':'40px'}">{{msg}}</h1>-->
<!--把样式对象定义到data中,再引用到:style-->
<!--<h1 id="h1" :style="styleObj">{{msg}}</h1>-->
<!--在:style中通过数组应用多个data上的样式-->
<h1 id="h1" :style="[styleObj,styleObj2]">{{msg}}</h1>
<script type="text/javascript">
var vm=new Vue({
el: '#h1',
data:{
msg:'我是一级标题',
styleObj:{color:'red','font-size':'40px'},
styleObj2:{fontStyle:'italic'}
}
})
</script>
</body>
过滤器
- 过滤器使用管道符:’|’
<div id="app">
<!--过滤器使用格式{{数据 | 过滤器名称}}-->
<p>{{msg | filter1}}</p>
</div>
<script type="text/javascript">
/*
创建过滤器
filter1:为过滤器名称
msg:传递过来的数据,通过管道符左边的传递的数据
*/
Vue.filter('filter1',function (msg) {
return msg.replace(/你/g,'他们');
})
var vm = new Vue({
el: '#app',
data: {
msg:'你好,你吃过了吗,你要去哪?'
}
})
</script>
- 过滤器还可以传入参数
<div id="app">
<!--过滤器使用格式{{数据 | 过滤器名称}}-->
<p>{{msg | filter1('他们','111')}}</p>
</div>
<script type="text/javascript">
//创建过滤器
Vue.filter('filter1',function (msg,arg,arg2) {
return msg.replace(/你/g,arg+arg2);
})
var vm = new Vue({
el: '#app',
data: {
msg:'你好,你吃过了吗,你要去哪?'
}
})
</script>
- 可以同时使用多个过滤器
<p>{{msg | filter1 |filter2 }}</p>
- 全局和私有过滤器
上面定义的是全局过滤器,下面定义私有过滤器
在new Vue({})中添加filters
filters: {//私有过滤器
dateFormat:function (dateStr,pattern='') {
//根据给定的时间字符串,得到特定的时间
var dt=new Date(dateStr);
//提取年月日
var y=dt.getFullYear();
var m=dt.getMonth()+1;//月份从0开始
var d=dt.getDate();
if(pattern.toLocaleLowerCase()=='yyyy-mm-dd'){
return `${y}-${m}-${d}`;
}else{
//最全时间格式
var hh=dt.getHours();
var mm=dt.getMinutes();
var ss=dt.getSeconds();
return `${y}-${m}-${d} ${hh}:${mm}:${ss}~~~~`;
}
}
}
当全局和私有过滤器同名且同时存在,就近原则,优先调用私有过滤器
字符串补充
- String.prototype.padStart(maxLength,fillString=‘xx’)或String.prototype.padEnd(maxLength,fillString=‘xx’)
字符串长度不足时padStart在左边补齐’xx’,padEnd在右边补齐’xx’
数组补充
- some
用于检测数组中的元素是否满足指定的条件。
数组名.some((str)=>{
return str==='xxx'
//如果有就是true否则为false
})
- splice(index,len,[item])
它也可以用来替换/删除/添加数组内某一个或者几个值(该方法会改变原始数组)
index:数组开始下标
len: 替换/删除的长度
item:替换的值,删除操作的话 item为空
this.list.some((item,i)=>{
if(item.id==id){
//删除下标从i开始,删除1个
this.list.splice(i,1);
return true;
}
})
按键修饰符
vue中提供的按键修饰符
https://cn.vuejs.org/v2/guide/events.html
在js中每个按键都对应具体的数字,可以直接使用,也可以自定义修饰符
<!--在js中f2对应113-->
<input type="text" class="form-control" v-model="name" @keyup.113="add">
<input type="text" class="form-control" v-model="name" @keyup.f2="add">
<script>
Vue.config.keyCodes.f2=113;
</script>
自定义指令
https://cn.vuejs.org/v2/guide/custom-directive.html
<input type="text" class="form-control" v-model="keywords" v-focus v-color>
//自定义指令名称为focus 使用时v-focus
Vue.directive('focus',{
//el参数,是一个原生的JS对象
inserted:function (el) {//在插入DOM时会执行一次
el.focus()
//Js行为相关的都在inserted中设置
}
})
Vue.directive('color',{
//指令绑定元素时操作,只会触发一次
bind:function(el){
//和样式相关的操作都在bind中操作
el.style.color='red';
}
})
传递颜色值
<input type="text" class="form-control" v-model="keywords" v-color="'blue'">
Vue.directive('color',{
//指令绑定元素时操作,只会触发一次
bind:function(el,binding){
//和样式相关的操作都在bind中操作
el.style.color=binding.value;
}
})
vue生命周期
vue-resource基本使用
https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
methods:{
getInfo(){
this.$http.get('http://10.3.242.250:3000/').then(response => {
console.log(response.body);
});
},
postInfo(){
this.$http.post('http://10.3.242.250:3000/list',{},{emulateJSON:true})
.then(result=>{
console.log(result.body)
})
},
jsonpInfo(){
this.$http.jsonp('ip地址').then(result=>{
console.log(result.body)
})
}
}
组件
-
什么是组件:
组件的出现 ,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
-
组件化和模块化的不同:
- 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
- 组件化:是从∪I界面的角度进行划分的;前端的组件化,方便∪I组件的重用;
创建组件方式
- Vue.extend()方式
<div id="app">
<!--使用驼峰-->
<!--<my-com1></my-com1>-->
<!--不适用驼峰,直接拿名字使用-->
<mycom1></mycom1>
</div>
<script type="text/javascript">
//使用Vue.extend来创建全局Vue组件
var com1=Vue.extend({
//通过template属性指定组件要展示的HTML结构
template:'<h2>只是使用Vue.extend创建的组件</h2>'
})
//使用Vue.component('组件名称',创建出来的组件模板对象)
/**
*Vue.component定义全局变量时,组件使用驼峰命名,则在引用组件的时候需要把大写的驼峰改成小写的字母,
* 同时,两个单词之间使用'-'链接
*
*如果不适用驼峰,则直接拿名称来使用
*/
/*Vue.component('myCom1',com1);*/
/*Vue.component('mycom1',com1);*/
/*两步合成一步*/
Vue.component('mycom1',Vue.extend({
//通过template属性指定组件要展示的HTML结构
template:'<h2>只是使用Vue.extend创建的组件</h2>'
}));
var vm = new Vue({
el: '#app',
data: {
msg:'ok'
},
methods:{
show(){
console.log('执行了show方法')
}
}
})
</script>
</body>
- Vue.component直接创建
/*两步合成一步*/
Vue.component('mycom2',{
//通过template属性指定组件要展示的HTML结构
template:'<h2>只是使用Vue.extend创建的组件</h2>'
});
无论时那种方式创建组件,template属性指向的模板内容,必须有且只能有唯一的一个根元素
3、template单独写
<div id="app">
<mycom3></mycom3>
</div>
<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
<div>
<h2>只是使用Vue.extend创建的组件</h2>
</div>
</template>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('mycom3',{
//通过template属性指定组件要展示的HTML结构
template:'#tmpl'
});
var vm = new Vue({
el: '#app',
data: {}
})
</script>
私有组件
- components
<div id="app">
<mycom4></mycom4>
</div>
<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
<div>
<h2>只是使用Vue.extend创建的组件</h2>
</div>
</template>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
components:{
mycom4:{
template:'#tmpl'
}
}
})
</script>
组件切换
- v-if和v-else
<div id="app">
<input type="button" value="登录" @click="flag=true">
<input type="button" value="祖册" @click="flag=false">
<!--通过flag的值来确定显示哪个组件-->
<login v-if="flag"></login>
<register v-else="flag"></register>
</div>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('login',{
template:'<h2>登录组件</h2>'
});
Vue.component('register',{
template:'<h2>注册组件</h2>'
})
var vm = new Vue({
el: '#app',
data: {
flag:true
}
})
</script>
- component占位符
<div id="app">
<input type="button" value="登录" @click="compName='login'">
<input type="button" value="注册" @click="compName='register'">
<!--component在这里就是一个占位符,通过:is来绑定一个组件并显示-->
<component :is="compName"></component>
</div>
<script type="text/javascript">
/*两步合成一步*/
Vue.component('login',{
template:'<h2>登录组件</h2>'
});
Vue.component('register',{
template:'<h2>注册组件</h2>'
})
var vm = new Vue({
el: '#app',
data: {
compName:'login'
}
})
</script>
父组件向子组件传递
- 父组件向子组件传递值
<div id="app">
<!--通过v-bind绑定一个parentmsg对象和父组件中的msg对象-->
<com1 v-bind:parentmsg="msg"></com1>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
/*定义子组件*/
components:{
//子组件无法默认访问到父组件中的data上的数据和methods中的方法
com1:{
//子组件中data数据是自身私有的,可以修改
data(){
return{
title:'123',
content:'qqq'
}
},
template:'<h2>这是子组件------{{parentmsg}}</h2>',
//props是一个数组类型,中的数据,都是父组件传递给子组件的,不可以修改
props:['parentmsg']
}
}
})
</script>
- 父组件向子组件传递事件
<div id="app">
<!--事件绑定需要使用v-on或简写@,自定义一个func事件变量,绑定show-->
<com1 @func="show"></com1>
</div>
<template id="tmp1">
<div>
<h1>这是子组件</h1>
<input type="button" value="这是子组件的按钮,点击它,触发父组件传递过来func方法" @click="myclick">
</div>
</template>
<script type="text/javascript">
//定义一个自变量类型的组件模板对象
var com1={
template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
methods:{
myclick(){
//通过调用子组件自身的$emit方法,传递自定义的事件名,如果方法有参数,对应传递参数
this.$emit('func','123')
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
/*定义子组件*/
components:{
com1
},
methods:{
show:function (data) {
console.log('这是父组件show方法'+data)
}
}
})
</script>
通过子组件调用父组件的事件,也可以把子组件的数据传递给父组件
非父子组件间数据传值
-
单独事件中心管理组件间的通信
var eventHub=new Vue() -
监听事件与销毁事件
eventHub. o n ( 函 数 名 , 函 数 体 ) e v e n t H u b . on(函数名,函数体) eventHub. on(函数名,函数体)eventHub.off(函数名) -
触发事件
eventHub.$emit(函数名,参数)
- 案例代码
<div id="app">
<div>
<span>父组件</span>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script>
//事件中心
var eventHub=new Vue();
//组件test-tom
Vue.component("test-tom", {
data() {
return {
num: 0
}
},
template: `
<div>
<h6>TOM:{{num}}</h6>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle:function(val){
eventHub.$emit('jerry-event',2);
}
},
mounted:function(){
//监听事件
eventHub.$on('tom-event',(val)=>{
this.num+=val;
})
}
});
//组件test-jerry
Vue.component("test-jerry", {
data() {
return {
num: 0
}
},
template: `
<div>
<h6>Jerry:{{num}}</h6>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle:function(val){
eventHub.$emit('tom-event',1);
}
},
mounted:function(){
//监听事件
eventHub.$on('jerry-event',(val)=>{
this.num+=val;
})
}
});
var vm=new Vue({
el:'#app',
data:{
},
methods: {
//注销事件
handle:function(){
eventHub.$off('tom-event');
eventHub.$off('jerry-event');
}
},
});
</script>
ref获取DOM元素和组件引用
<div id="app">
<input type="button" value="show" @click="show">
<!--通过在元素中添加ref属性,讲指定名称的组件添加到vue中的refs-->
<h3 id="myh3" ref="myh3">今天天气真好!</h3>
<com1 ref="com1"></com1>
</div>
<template id="tmp1">
<div>
<h1>这是子组件</h1>
</div>
</template>
<script type="text/javascript">
//定义一个自变量类型的组件模板对象
var com1={
template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
methods:{
myclick(){
console.log('子组件事件')
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg:'这是父组件中的值'
},
methods:{
show:function () {
/*通过this.$refs.元素名称进行访问*/
console.log(this.$refs.myh3.innerText)
this.$refs.com1.myclick()
}
},
/*定义子组件*/
components:{
com1
}
})
</script>
前端路由和后端路由
什么是路由
- 后端路由: 所有超链接都是URL地址,所有URL地址都对应服务器上对应的资源;
- 前端路由: 对于单页面应用程序,主要通过URL中的hash(#号)来实现单页面不同位置之间的切换;hash有一个特点:HTTP请求不会包含hash相关内容。
- 在单页面通过hash改变来切换页面内容的方式,称作前端路由(区别于后端路由)
- 参考链接:https://www.cnblogs.com/joyho/articles/4430148.html
vue-router基本使用
- 引入对应js资源,需要依赖vue
- 创建VueRouter实例
- 在实例中添加对应的路由匹配规则
- 在Vue实例中添加 2中的VueRouter实例
- 在对应Vue控制区域添加占位符
<div id="app">
<!--<a href="#/login">登录</a>
<a href="#/register">注册</a>-->
<!--vue-router提供的元素,router-link默认渲染为一个 a标签,通过tag可以指定渲染成对应标签-->
<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register">注册</router-link>
<!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
<router-view></router-view>
</div>
<script type="text/javascript">
//登录组件模板对象
var login={
template: '<h2>登录组件</h2>'
}
//登录组件模板对象
var register={
template: '<h2>注册组件</h2>'
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{path:'/login',component:login},
{path:'/register',component:register}
]
})
var vm = new Vue({
el: '#app',
data: {},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
</script>
上面代码中需要注意,使用点击超链接流程是:超链接改变请求地址的hash,然后在根据请求地址请求匹配对应的组件
- 路由redirect重定向
在上面的案例中第一次进入页面应该展示登录组件比较合理,这个时候可以采用
{path:'/',component:login}
但是地址栏上#/显示的却是登录组件,会给用户带来困惑
所以我们可以使用vue-router提供的redirect
{path:'/',redirect:'/login'},
- router-link 控件点击激活样式
通过上面案例,点击 router-link会自动在该控件上添加类:router-link-active
该类是由VueRouter实例中的linkActiveClass指定的所以修改控件点击样式有2种方式
<style>
.myactive{
color:red;
}
/*方式二重写默认样式的router-link-active*/
.router-link-active{
color:blue;
}
</style>
<div id="app">
<!--vue-router提供的元素,router-link默认渲染为一个 a标签,通过tag可以指定渲染成对应标签-->
<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register">注册</router-link>
<!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
<router-view></router-view>
</div>
<script type="text/javascript">
//登录组件模板对象
var login={
template: '<h2>登录组件</h2>'
}
//登录组件模板对象
var register={
template: '<h2>注册组件</h2>'
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{path:'/',component:login},
//{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
</script>
- 路由传参
1.参数保存在query中
在上面案例代码中修改如下代码
<router-link to="/login?id=10" tag="span">登录</router-link>
通过浏览器命令终端可以看到query中保存了传递的参数
在代码中输出路由传递的参数
//登录组件模板对象
var login={
template: '<h2>登录组件--{{$route.query.id}}</h2>',
created(){//组件生命周期钩子函数
console.log(this.$route.query.id)
}
}
- 参数保存在params中
vue-router提供了一套参数正则匹配
/:id/:name
在传参时,通过/12/zhagnsan
在vue中的Router中的params中会生成
id:12
name:zhagnsan
修改代码如下
<router-link to="/login/12/ls">登录</router-link>
<script>
//登录组件模板对象
var login={
template: '<h2>登录组件--{{$route.params.id}}--{{$route.params.name}}</h2>',
created(){//组件生命周期钩子函数
console.log(this.$route.params.id)
console.log(this.$route.params.name)
}
}
<!--在路由匹配规则中使用:名称-->
{path:'/login/:id/:name',component:login}
</script>
- 路由的嵌套
<div id="app">
<router-link to="/account">account</router-link>
<!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
<router-view></router-view>
</div>
<template id="tmp1">
<div>
<h1>这是Account组件</h1>
<router-link to="/account/login">登录</router-link>
<router-link to="/account/register">注册</router-link>
<router-view></router-view>
</div>
</template>
<script type="text/javascript">
var account={
template:'#tmp1'
}
//登录组件模板对象
var login={
template: '<h2>登录组件</h2>',
}
//登录组件模板对象
var register={
template: '<h2>注册组件</h2>',
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
/**
* 每个路由匹配规则都是一个对象,每个对象必须有2个属性
* 属性1 path,表示监听那个路由链接地址
* 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
*/
{
path:'/account',
component:account,
/*children子路由*/
children:[
/*子路由的path前面不要带 / ,否则永远从根路径开始请求*/
{path:'login',component:login},
{path:'register',component:register}
]
}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
</script>
- 路由使用命名视图
在router-view控件中使用name属性来指定显示组件
<div id="app">
<!--没有标记name的使用默认-->
<router-view></router-view>
<router-view name="left"></router-view>
<router-view name="main"></router-view>
</div>
<script type="text/javascript">
var header={
template:'<h2>头组件</h2>'
}
//登录组件模板对象
var left={
template: '<h2>左侧组件</h2>',
}
//登录组件模板对象
var main={
template: '<h2>右侧组件</h2>',
}
/*第二步创建VueRouter实例*/
//创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
var routerObj=new VueRouter({
/*路由匹配规则数组,注意是routes*/
routes:[
{
path:'/',
/*注意这里是components*/
components:{
/*左边名称会自动添加引号*/
default:header,
left:left,
left:main
}
}
],
/*方式一自定义指定样式*/
//linkActiveClass:'myactive'
})
var vm = new Vue({
el: '#app',
data: {},
router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
})
</script>
watch、computed
- watch文本监听
输入名和字来拼接出全名
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">
<input type="text" v-model="fullname">
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
firstname:'',
lastname:'',
fullname:''
},
watch:{
/*watch可以监视data中指定数据的变化,然后触发这个watch中对应的function处理函数*/
firstname: function (newVal,oldVal) {
this.fullname=newVal+'-'+this.lastname
},
lastname: function (newVal,oldVal) {
this.fullname=newVal+'-'+this.lastname
},
}
})
</script>
- computed
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">
<input type="text" v-model="fullname">
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: ''
},
/*
* 在computed中可以定义一些属性,叫做【计算属性】,计算属性的本质就是一个方法
* 计算属性可以直接当做属性来使用,并不会把计算属性当做方法来调用
* 计算属性function内部如果用到了data数据,只要其中发生了变化,就会立即重新计算。
* 计算属性的求值结果会被缓存起来,方便下次使用。
* */
computed: {
'fullname': function f() {
return this.firstname+'-'+this.lastname
}
}
})
</script>
- watch、computed和methods之间的对比
- computed 属性的结果会被缓存,除非依赖的响应式属性変化オ会重新计算.主要当作属性来使用
- methods 方法表示一个具体的操作,主要书写业务逻辑;
- watch 个対象,键是需要观察的表达式,值是对应回调函数.主要用来监听某些特定数据的变化,从而迸行某些具体的逻辑操作;可以看作是computed和methods 结合体;
webpack
什么是webpack
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
使用webpack
- 安装
全局安装
npm install -g webpack
局部安装
npm install --save-dev webpack
- 使用前的准备
-
创建文件目录如下
-
在项目文件的根目录下,创建package.json 文件,这是一个npm说明文件。
npm init
输入这个命令后,终端会提出一系列问题,一般默认即可,也可以使用npm init -y。在项目目录下,自动创建package.json 文件。
-
package.json文件已经就绪,在项目中安装webpack依赖包
npm install --save-dev webpack
- 基础使用
现在需要实现一个功能:页面显示多个列表行,奇数行和偶数行背景颜色不同
index.html
<!-- 网页入口 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <script src="./main.js"> </script> -->
<title>首页</title>
<!-- <script src="/buddle.js"></script> -->
</head>
<body>
<ul>
<li>这是第1个li</li>
<li>这是第2个li</li>
<li>这是第3个li</li>
<li>这是第4个li</li>
<li>这是第5个li</li>
<li>这是第6个li</li>
<li>这是第7个li</li>
<li>这是第8个li</li>
<li>这是第9个li</li>
<li>这是第10个li</li>
</ul>
</body>
</html>
项目安装jquery
npm install jquery --save 缩写
npm i jquery -S
补充npm i 安装命令中的 -g -D -S的区别
https://blog.csdn.net/qq_32202099/article/details/100005445
main.js
//项目的js入口文件
//导入jquery
import $ from 'jquery'
// const $ = require('jquery')
$(function(){
$('li:odd').css('backgroundColor','black')
$('li:even').css('backgroundColor',function(){
return '#'+'D97634'
})
})
因为在main.js中使用了import命令,这是ES6代码,浏览器解析不了。所以需要使用webpack继续解析成对应js文件
webpack .\src\main.js .\dist\bundle.js
在index.js文件中引入这个bundle.js文件即可。
当修改main.js文件内容时,需要重新手运行webpack .\src\main.js .\dist\bundle.js比较麻烦。现在引入webpack配置文件
在项目根目录下创建 webpack.config.js
const path=require('path')
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录中去
filename: 'bundle.js'//指定输出文件的名称
}
}
现在再次修改main.js文件后,可以直接运行webpack命令即可
修改main.js自动编译
本地安装 webpack-dev-server插件,实现自动打包编译功能
npm i webpack-dev-server -D
因为是本地安装,不能在终端直接使用 webpack-dev-server命令,所以需要在package.json中配置
"scripts": {
....,
"dev": "webpack-dev-server"
},
在命令行中可以直接运行
npm run dev
注意: 运行webpack-dev-server生成的bundle.js是在内存中的,路径是/bundle.js,所以需要修改一下index.js中的引用。
webpack-dev-server常用参数配置方式一
在package.json中配置,方便
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
},
–open:启动webpack-dev-server自动打开浏览器
–port 3000 :端口号
–contentBase src:默认打开网页目录
– hot:热更新,不用每次都生成全新的bundle.js文件
webpack-dev-server常用参数配置方式一
在webpack.config.js中配置,比较麻烦
直接查看js文件
const path=require('path')
//启动热更新的第二步
const webpack=require('webpack')
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
filename: 'buddle.js'//指定输出文件的名称
},
devServer:{//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
// --open --port 3000 --contentBase src --hot
open:true,//自动打开浏览器
port:3000,//设置启动时运行端口
contentBase:'src',//指定托管的跟目录
hot:true//启动热更新的第一步
},
plugins:[//配置插件的结点
//启动热更新第三步
new webpack.HotModuleReplacementPlugin(),
]
}
安装配置 html-webpack-plugin
自动在内存中根据指定页面生成一个内存页面
安装 npm i html-webpack-plugin -D
配置
const path=require('path')
//启动热更新的第二步
const webpack=require('webpack')
//导入内存中生成HTML页面的插件
//只要是插件都需要放到 plugins结点中
//这个插件的两个作用:
// 1. 自动在内存中根据指定页面生成一个内存页面
// 2. 自动,把打包好的bundle.js追加到页面中去
const htmlWebpackPlugin=require("html-webpack-plugin")
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
output:{
path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
filename: 'buddle.js'//指定输出文件的名称
},
devServer:{//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
// --open --port 3000 --contentBase src --hot
open:true,//自动打开浏览器
port:3000,//设置启动时运行端口
contentBase:'src',//指定托管的跟目录
hot:true//启动热更新的第一步
},
plugins:[//配置插件的结点
//启动热更新第三步
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
template: path.join(__dirname,'./src/index.html'),//指定模板页面,将来会根据指定的页面,去内存生成内存中的页面
filename: 'index.html'//指定生成页面的名称
})
]
}
运行 npm run dev,会访问内存中生成的index.html页面,页面会自动在body末尾添加内存中bundle.js文件的应用。
处理css文件的第三方loader
webpack默认只能打包处理JS类型的文件,处理非JS类型的文件,需要手动安装一些合适的第三方loader加载器。处理css文件,需要安装style-loader、css-loader。
npm i style-loader css-loader -D
在webpack.config.js配置文件中,新增配置结点 module对象,在这个module对象身上,有一个rules属性,这个属性是一个数组,存放所有第三方文件的匹配和处理规则。
module:{
rules:[
{test:/\.css$/,use:['style-loader','css-loader']},//配置处理css文件的第三方loader规则
]
}
处理less文件的第三方loader
npm i less-loader -D
出现没有安装的依赖,需要继续安装
{test:/\.less$/,use:['style-loader','css-loader','less-loader']},//处理less文件的第三方loader规则
处理scss文件的第三方loader
npm i sass-loader -D
出现没有安装的依赖,需要继续安装
{test:/\.less$/,use:['style-loader','css-loader','sass-loader']},//处理scss文件的第三方loader规则
处理图片文件的第三方loader
npm i url-loader file-loader -D
其中file-loader是url-loader的依赖包,出现没有安装的依赖,需要继续安装
{test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader'},//处理图片文件的第三方loader规则
loader设置参数:
{test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader?limit=7631&name=[name].[ext]'}
其中limit给定值是图片的大小,单位是byte,引用的图片如果大于等于给定值,则不会转成base64格式字符串,否则转成base64格式字符串
name=[name].[ext]:[name] 代表之前什么名,转换后还是什么名;.[ext]之前什么后缀名,转换后还是什么后缀名。
如果希望前面加上hash:name=[hash:8]-[name].[ext]:[name]:天面添加8位hash值。
处理字体图标的第三方loader
使用的loader还是url-loader。这里引用bootstrap中的字体图标。
npm i bootstrap@3.3.7 -S
注意这个案例中需要引入bootstrap@3.3.7
到bootstrap官网上找一个组件:
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
在main.js中引入bootstrap.css依赖
//如果通过路径形式引入node_modules中的相关文件,可以省略路径前面的node_modules这一层目录。默认会取node_modules中查找
import 'bootstrap/dist/css/bootstrap.css'
在webpack.config.js中添加匹配处理规则
{test:/\.(|eot|svg|ttf|woff|woff2)$/,use:'url-loader'},//处理文字文件的第三方loader规则
注意:json文件中不能有注释
webpack中babel配置
在webpack中,默认只能处理一部分ES6的新语法,一些更高级的ES6语法或ES7语法需要借助第三方loader将其处理为低级语法后,再把结果交给webpack去打包到bundle.js中。
-
安装两套包,安装Babel的loader功能
- npm i babel-core babel-loader@7 babel-plugin-transform-runtime -D
- npm i babel-preset-env babel-preset-stage-0 -D
-
在webpack.config.js文件中配置匹配规则
{test:/.js&/,use:'babel-loader',exlude:/node_modules/}
exlude用来排除对应的文件包,只需要解析我们自己写的js文件。
- 在项目的根目录中新建一个叫 .babelrc的babel配置文件,这个配置文件属于JSON格式,所以在写.babelrc配置的时候,必须符合JSON语法规范:不能写注释,字符串必须用双引号。
{
"presets":["env","stage-0"],
"plugins":["transform-runtime"]
}
vue中render函数渲染组件
<div id="app">
</div>
<script>
var login={
template:'<h1>这是登陆组件</h1>'
}
var vm=new Vue({
el:'#app',
data:{},
methods:{},
//createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
render:function(createElements){
//注意,这里的return结果会替换页面中el指定的那个容器
return createElements(login)
}
});
</script>
在webpack使用vue
安装vue
npm i vue -D
在main.js中引入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属性指定了这个包在被加载的时候,入口文件】
var login={
template:'<h1>这是登陆组件</h1>'
}
var vm=new Vue({
el:'#app',
data:{},
methods:{},
//createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
render:function(createElements){
//注意,这里的return结果会替换页面中el指定的那个容器
return createElements(login)
}
});
引入vue的第二种方式
main.js
//方式二
import Vue from 'vue'
在webpack.config.js
resolve:{
alias:{
"vue$":"vue/dist/vue.js"
}
}
使用vue的runtime-only模式
在runtime-only模式,需要把vue模板template放到对应的.vue文件中
在src目录下建立login.vue文件
/* 模板 */
<template>
<div>
<h1>这是登陆组件</h1>
</div>
</template>
/* 业务逻辑 */
<script></script>
/* 样式 */
<style></style>
安装配置处理vue文件的loader
npm i vue-loader -D
在webpack.config.js文件中配置插件
const VueLoaderPlugin = require('vue-loader/lib/plugin');
plugins:[//配置插件的结点
// make sure to include the plugin for the magic
new VueLoaderPlugin()
],
main.js
import Vue from 'vue'
import login from './login.vue'
var vm=new Vue({
el:'#app',
data:{},
methods:{},
render:function(createElements){
return createElements(login)
}
});
export default和export使用方法
在login.vue组件文件中,添加数据变量
<template>
<div>
<h1>这是登陆组件-----{{msg}}----{{title}}</h1>
</div>
</template>
<script>
export default{
data(){
//注意组件中的data必须是function
return {
msg:'123',
title:'小星星'
}
},
methods:{
show(){
console.log("调用了login.vue 中的show方法");
}
}
}
</script>
<style></style>
在src目录下新建test.js
//再Node中向外暴露成员的形式:
//module.exports和exports暴露成员
//var 名称=require('模块标识符') 接收成员
//在ES6中,使用export default 和export 向外暴露成员;使用import 模块名称 from '模块路径'
//一个模块 只能使用export default向外暴露一次
export default{
name:'ly',
sex:'男'
}
//export可以多次使用,并且可以和export default 一起使用
export var title='大猩猩'
在main.js中引入test.js文件
//接收,其中export需要使用{}来接收,称为【按需导出】,使用as可以换名
import person,{title as title11} from './test.js'
console.log(person)
console.log(title11)
webpack 使用vue-router
- 安装vue-router
npm i vue-router -S
- 项目准备
在src目录下建立main文件夹,文件夹中建立Account.vue和GoodsList.vue
/* Account.vue */
<template>
<div>
<h1>这是account组件</h1>
</div>
</template>
<script>
</script>
<style></style>
/* GoodsList.vue */
<template>
<div>
<h1>这是goodslist组件</h1>
</div>
</template>
<script>
</script>
<style></style>
在src下建立新文件login.vue
<template>
<div>
<h1>这是登陆组件</h1>
<router-link to="/account">Account</router-link>
<router-link to="/goodslist">GoodsList</router-link>
<router-view></router-view>
</div>
</template>
<script>
</script>
<style></style>
-
在main.js中引入vue-router
//项目的js入口文件 import Vue from 'vue' //1. 导入vue-router包 import VueRouter from 'vue-router' import login from './login.vue' import account from './main/Account.vue' import goodslist from './main/GoodsList.vue' //2. 手动安装VueRouter Vue.use(VueRouter) //3. 创建路由对象 var router = new VueRouter({ routes:[ {path:'/',redirect:'/account'}, {path:'/account',component:account}, {path:'/goodslist',component:goodslist} ] }) var vm=new Vue({ el:'#app', data:{}, methods:{}, render:function(createElements){ return createElements(login) }, router });
组件中style标签
- scoped标签
在Vue组件中的style中设置样式,默认是全局效果
<style>
div{
font-style: italic;
}
</style>
通过添加scoped属性来限制为当前组件的样式
<style scoped>
div{
font-style: italic;
}
</style>
scoped属性是通过属性选择器的方式起作用的
- lang标签
在style中可以使用less和scss文件格式通过lang属性来指定
<style lang="scss" scoped>
body{
div{
font-style: italic;
}
}
</style>
抽离路由模块
基本原则,把路由配置部分的代码从main.js中抽离出来,放到一个和mian.js同级的文件 router.js文件中。
补充知识
-
变异方法:修改原始数据
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
-
-
替换数组:生成新的数组
-
filter()
-
concat()
-
slice()
-
-
Vue数组响应式变化
-
Vue.set(vm.items,indexOfItem,newValue)
-
vm.$set(vm.item,indexOfItem,newValue)
参数1:数组名称
参数2:数组索引
参数3:要处理的值
-
<div id="app">
<li :key="index" v-for="(item,index) in list">{{item}}</li>
</div>
<script>
var vm=new Vue({
el:'#app',
data: {
list:["apple","orange","lemon"]
},
});
//修改在页面无响应
//vm.list[1]="pear";
//响应方式1
//Vue.set(vm.list,1,'pear');
vm.$set(vm.list,1,'pear');
</script>
通过上面两个方式也可以向对象中添加值
Vue.set(vm.object,‘key’,value)
插槽slot
slot基础用法
在子组件内使用元素可以为该子组件开启一个插槽,在父组件模板中,插入子组件标签内的所有内容将替代子组件的标签及它的内容。
<div id="app">
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>
</div>
<script>
//组件test-jerry
Vue.component("alert-box", {
template: `
<div>
<span>Error:</span>
<slot>默认值</slot>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
具名插槽
给组件中的元素指定一个name可以在父组件中指定内容填充到子组件中,父组件中没有对应的name会填充到匿名slot中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.header{
color: red;
}
.footer{
color: blue;
}
</style>
</head>
<body>
<div id="app">
<base-layout>
<!-- <p slot="header">标题信息</p>
<p >主要内容1</p>
<p >主要内容2</p>
<p slot="footer">底部信息</p> -->
<!-- template标签起到打包多个内容插入指定name的插槽中 -->
<template slot="header">
<div>
<p slot="header">标题信息1</p>
<p slot="header">标题信息2</p>
</div>
</template>
<p >主要内容1</p>
<p >主要内容2</p>
<template slot="footer">
<div>
<p slot="footer">底部信息1</p>
<p slot="footer">底部信息2</p>
</div>
</template>
<!-- 填充到子组件中的匿名slot中 -->
<p >主要内容3</p>
</base-layout>
</div>
<script>
Vue.component("base-layout",{
template:`
<div>
<header class='header'>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer class='footer'>
<slot name='footer'></slot>
</footer>
</div>
`
})
var vm=new Vue({
el:'#app'
})
</script>
</body>
</html>
上面案例运行结果图:
作用域插槽
应用场景:父组件对子组件的内容进行加工处理
<div id="app">
<fruit-list :list='list'>
<!-- 插槽内容:template包裹,通过slot-scope属性获取子组件中插槽中的数据(slotProps随便命名) -->
<template slot-scope='slotProps'>
<strong v-if="slotProps.item.id==1">{{slotProps.item.name}}</strong>
<span v-else>{{slotProps.item.name}}</span>
</template>
</fruit-list>
</div>
<script>
Vue.component("fruit-list",{
props:['list'],
template:`
<div>
<li :key='item.id' v-for='(item,index) in list'>
<!-- 插槽定义:使用v-bind来绑定一个变量来传递给父组件,item随便命名 -->
<slot v-bind:item='item'>
{{item.name}}
</slot>
</li>
</div>
`
})
var vm=new Vue({
el:'#app',
data:{
list:[
{
id:1,
name:'apple'
},
{
id:2,
name:'orange'
},
{
id:3,
name:'banana'
}
]
}
})
</script>
vue前后端交互
Promise用法
-
实例化Promise对象,构造函数中传递函数,该函数用于处理异步任务。
-
resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果。
<script>
var p=new Promise(function(resolve,reject){
var flag=true;
if(flag){
resolve('hello world!');
}else{
reject('错误结果');
}
});
p.then(function(ret){
//从resolve处理逻辑
console.log(ret);
},function(ret){
//reject处理逻辑
console.log(ret);
});
</script>
- 基于Promise处理Ajax请求
这里需要了解一下原生ajax请求步骤
<script>
//基于Promise处理Ajax请求
function queryData(url){
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){
//处理正常的情况
resolve(xhr.responseText);
}else{
reject('服务器错误');
}
}
xhr.open('get',url);
xhr.send(null);
});
return p;
}
queryData(url1)
.then(function(data){
console.log(data);
//小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法
return queryData(url2);
})
.then(function(data){
console.log(data);
})
</script>
-
then参数中的函数返回值
- 返回Promise实例对象
返回的实例对象会调用接下来的then,就是上面案例所示。
- 返回普通值
返回的普通值会直接传递给下一个then(),通过then()参数中的函数来接收该值,因为没有返回Promise对象,默认会创建一个Promise对象,所以依旧可以调用then()方法。
queryData(url) .then(function(data){ console.log(data); //小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法 return "hello"; }) .then(function(data){ console.log(data); })
-
Promise的实例方法
-
p.then():得到异步任务的结果
-
p.catch():获取异常信息
-
p.finally():成功与否都会执行
<script> var p=new Promise(function(resolve,reject){ var flag=false; if(flag){ resolve('hello world!'); }else{ reject('错误结果'); } }); p.then(function(ret){ //从resolve处理逻辑 console.log('then:'+ret); }) //当执行reject时,会执行,相当于then方法中第二个函数 .catch(function(data){ console.log("catch:"+data); }) //无论成功失败,都会执行 .finally(function(){ console.log('finally'); }) </script>
-
-
Promise中对象方法
-
Promise.all()并发处理多个异步任务,所有任务都执行完成才得到结果
-
Promise.race()并发处理多个异步任务,只要一个任务完成就得到结果,其他的异步任务也会执行,但是不获取结果。
//获取p1,p2,p3对应的返回结果 Promise.all([p1,p2,p3]).then((result)=>{ console.log(result) }) //只获取p1对应的返回结果 Promise.race([p1,p2,p3]).then((result)=>{ console.log(result) })
-
fetch 用法
- fetch基础用法
fetch(url).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
- fetch请求参数
常用配置选项
method(String):HTTP请求方法,默认为Get(POST、PUT、DELETE)
body(String):http请求的参数
header(Object):http请求头,默认为{}
fetch(url,{
method:'get'
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
Get和Delete方式传参数一般有两种:?xxx=‘xxx’&yyy=‘yyy’,vue通过 query获取
/:id/name ,vue中通过params获取
post和put传参
//字符串格式
fetch(url,{
method:'post',
body:'name=lisi&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
//json格式
fetch(url,{
method:'post',
body:JSON.stringify({
name:'lisi',
pwd:'123'
}),
headers:{
'Content-Type':'application/json'
}
}).then(function(data){
//返回Promise对象,用于获取后台返回的数据
return data.text();
})
//Promise通过then方法,来处理其中的数据
.then(function(data){
console.log(data);
})
vue脚手架
创建vue项目
查看版本
vue -V
- 基于3.x版本的脚手架创建Vue项目:
安装
npm install -g @vue/cli 1).使用命令创建Vue项目
命令:vue create my-project
选择Manually select features(选择特性以创建项目)
勾选特性可以用空格进行勾选。
是否选用历史模式的路由:n
ESLint选择:ESLint + Standard config
何时进行ESLint语法校验:Lint on save
babel,postcss等配置文件如何放置:In dedicated config files(单独使用文件进行配置)
是否保存为模板:n
使用哪个工具安装包:npm
-
基于ui界面创建Vue项目
命令:vue ui
在自动打开的创建项目网页中配置项目信息。 -
基于2.x的旧模板,创建Vue项目
npm install -g @vue/cli-init
vue init webpack my-project -
分析Vue脚手架生成的项目结构
node_modules:依赖包目录
public:静态资源目录
src:源码目录
src/assets:资源目录
src/components:组件目录
src/views:视图组件目录
src/App.vue:根组件
src/main.js:入口js
src/router.js:路由js
babel.config.js:babel配置文件
.eslintrc.js: eslint语法配置文件
配置vue项目
配置项目启动自动打开浏览器及端口:
- 在package.json中
"vue":{
"devServer":{
"port":8888,
"open":true
}
}
- 在项目根目录下创建 vue.config.js文件
module.exports={
devServer:{
//自动打开浏览器
open:true,
port:8878
}
}
注意: 两种配置方式只能同时使用一种
Element-UI
Element-UI:一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面组件库
基于命令行方式手动安装
- 安装依赖包
npm i element-ui -S
- 导入Element-UI相关资源
//导入element-ui库
import ElementUI from 'element-ui'
//导入element-ui相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置Vue插件
Vue.use(ElementUI)
基于图形化界面自动安装
-
运行vue ui命令,打开图形化界面
-
通过vue项目管理器,进入具体的项目配置面板
-
点击插件->添加插件,进入插件查询面板
-
搜索vue-cli-plugin-element并安装
-
配置插件,实现按需导入。