11-Vue

Vue

  • 国产渐进式javaScript框架
  • 易用:熟悉HTML CSS javaScript可快速上手
  • 灵活:在一个库和一套完整的框架之间自如伸缩
  • 高效:20KB运行大小,超快虚拟DOM(渲染页面速度超快)
  • 运行原理:Vue代码>Vue框架解析>js原生代码
Vue基本语法
  • MVVM设计思想
  • M模型(model) Data
  • V视图(view) DOM
  • VM视图模型 new Vue({}) 实现控制逻辑

Vue实例化对象的属性

  • new Vue({}) 内的this指向它的实例对象vm (Vue框架内部对this进行了处理)
  • {{数据}} 插值表达式 (将数据填充到HTML中 可以进行一些简单的运算)
  • el : 元素的挂载位置 (可以是css选择器也可以是DOM元素)
  • data: 模板数据
  • methods : 专门用于存放事件的方法 v-on执行的值直接调用这里面的方法
  • directives: 局部自定义指令创建
    • 只能在该实例(组件)中使用
  • computed:计算属性 设置插值表达式中函数 不需要用()调用
  • watch: 侦听器属性 当监听的数据发生变化时触发
  • filters: 局部过滤器创建 对调用的数据进行函数内的逻辑处理
    • 只能在该实例(组件)中使用
//引入vue文件
<script src="./vue.js">script>
<div id="app">
    <h2>{{msg}}h2>
div>
<script>
var vm = new Vue({
	el:'#app',
	data:{
		msg:'hellow vue',
        num:0
	}
    methods:{
    	handle:function(){
    		this.num++;
		}
	},
    directives:{
		focus:{
            //el指当前使用这个指令的DOM元素
			inserted:function(el){
				el.focus()
			}
		}
	},
    computed:{
        reverseString:function() {
            //这里的this指当前vue实例对象
            return:this.msg.split('')
        }
    },
    watch:{
        msg:function(val) {
            console.log(val)
        }
    },
    filters:{
        过滤器名称:function(val) {
            return value.charAt(0)
        }
    }
})
script>

模板语法

  • 模板+数据 = 前端渲染(静态HTML内容)
  • 比起前端模板引擎多出了更多的模板语法
指令v-text v-html
  • 指令的本质就是自定义属性
  • Vue指令的格式以v-开始
  1. v-cloak(了解)

    • 插值表达式是需要解析完才会将解析完的代码显示在页面上,如果刷新过慢会导致用户先看到插值表达式
    • 解决方案:先隐藏,替换好值再隐藏
    //1.提供样式
    <style>
    	[v-clock]{
    		display:none
    	}
    style>
    //在插值表达式所在标签添加v-clock指令(也就是自定义属性)
    <div v-clock>{{msg}}div>
    
  2. v-text 填充纯文本(可以解决’闪动’问题 比v-cloak更方便)

    <div v-text="msg">div>  
    
  3. v-html 比起v-text 可以解析html标签(存在安全隐患)

    • 存在安全隐患(xss攻击),本网站数据可以使用 跨域(非同源) 不可使用
    • xss攻击:javascript脚本攻击,因为会解析script标签 可能会被人恶意传输死循环数据等
    <div v-html="msg1">{{msg}}div>
    
  4. v-pre 显示原始信息 跳过编译(原文输出)

    {{msg}}
    // html显示{{msg}}
数据响应式v-noce
  • 数据的响应式:数据的变化会影响页面变化

  • 数据绑定:插值表达式和data数据就是绑定的关系 data更改 插值表达式就会变动

  • v-once 只编译一次 显示内容之后就不再具有响应式功能(系统就不再监听这个数据,提高了性能)

    <div v-noce>{{msg1}}div>
    
双向数据绑定v-model
  • 数据的变化会影响页面,而页面的变动不会改变数据的变化,这是单向的

  • 双向:模型(数据)的变化视图(页面)会变化,视图(页面)变化模型(数据)也会变化

  • v-model="" 引号中填data input的val变化 这个数据的值也会跟着变化

    <input type="text" v-model="data"/>
    

事件绑定v-on

  • 指令用法 v-on:事件类型=“事件处理”
  • 简写方式 @事件类型=“事件处理”
//可以逻辑运算
<input type="button" @click="num++"/>
//也可以传递函数 这个函数是new Vue内设置
<input type="button" v-on:click="handle()"/>
事件函数参数传递
//事件绑定函数名称,默认传递一个事件函数
<input type="button" @click="handle"/>
//事件绑定函数调用,参数传递多个  要传递事件函数$event
<input type="button" @click="handle(1,2,$event)"/>
事件修饰符 stop prevent
//阻止事件冒泡  v-on:click.stop    
<a href="http://www.baidu.com" v-on:click.stop="fn()">跳转a>
//阻止事件默认行为 v-on:click.prevent
<a href="http://www.baidu.com" v-on:click.prevent="fn()">跳转a>
//修饰符还可以串联  v-on:click.stop.prevent
按键修饰符 enter delete
//按下回车键时触发事件
<input v-on:keyup.enter="submit"/>
//按下退格键时触发事件
<input v-on:keyup.delete="handle"/>

自定义按键修饰符

//给112keyCode码起个 f1名字    
Vue.config.keyCodes.f1 = 112;
//按下f1(keycode码为112) 触发submit事件
<input v-on:keyup.f1="submit"/>

属性绑定v-bind

//语法1   url为data对象内的属性 其值为链接
<a v-bind:href="url">百度a>
//简写语法   
<a :href="url">百度a>
v-model底层原理
//v-bind 将模型影响视图
//v-on:input 视图改变时调用函数影响视图
<input	type="text" v-bind:value="msg" v-on:input="msg=$event.target.value">
class样式处理
  • 对象的属性就是类名,这个属性的值是data属性的话,它的值要设置成布尔值
  • 数组的值如果是字符串,那它的值就是类名 (数组的布尔值为真)
  • 数组的值如果是对象 data属性中这个对象的属性和值就是 类名对应布尔值 active:true
//active是样式名称  isActive是data的属性,值为布尔值,值为true添加这个类名 否则不添加 
//可以通过调用方法更改 data属性isActive的值
//对象语法
<div v-bind:class="{active:isActive}">div>
//数组语法 数组元素为data的属性  值为类名
<div v-bind:class="[activeClass]">div>
//对象绑定和数组绑定可以结合使用 
<div v-bind:class="[activeClass,{test:isTest}]">div>
//简化操作   
<div v-bind:class="arrClass">div>
<div v-bind:class="objClass">div>
data:{
	arrClass:['active','error'] //data属性中设置值为数组 active和error为类名
	objClass:{
		active:true,
		error:true
	}
}
//默认的class会保留  此处div有两个class
<div class="base" v-bind:class="[activeClass]">div>

style样式绑定

  • 和class样式处理一样都可以进行对象语法,数组语法,简化的方式操作
//对象语法  对象内data属性的值为字符串样式
<div v-bind:style="{color:activeColor,fontSize:fontSize}">div>
	activeColor:'blue'
//数组语法  数组元素的data属性的值为对象 对象内属性为样式和值为样式值
<div v-bind:style="[arrStyle]">div>
	arrStyle:{
      	color:'red',
        backgroundColor:'skyblue'
   }

分支结构用法

分支循环结构if show
  • 根据分号中的条件表达式渲染其中一个div 其他不在DOM结构中
  • v-if是控制元素(结构)
<div v-if="num>=10">大于10div>
<div v-else-if="num<10&&num>0">0~10之间div>
<div v-else>小于0div>
data:{
	num:5
}
  • v-show 是控制样式(display:none) DOM中有这个元素 只不过是隐藏了
<div v-show="false">大于10div>
data:{
	flag:false
}

循环结构v-for

  • v-for 遍历数组
  • item是数组中的当前循环元素 index是当前循环元素的索引
<ul>
    <li v-for="item in fruits">{{item}}li>       //方式1 不带索引
    <li v-for="(item,index)in fruits">{{item}}{{index}}li>   //方式2 带索引
ul>	
data:{
	fruits:['apple','orange']
}
  • v-key : 帮助vue区别不同的元素 从而提高性能
  • v-for中加 :key 可以提高性能 如果数组元素不是对象没有id 填索引也可以
<li v-for="(item,index)in fruits" :key="item.id">{{item}}{{index}}li>
data:{
	fruits:[{
        id:1,
        ename:'apple'
	},{
		id:2,
		ename:'orange'
	}]
}
  • v-for遍历对象
  • v-if可以和 v-for结合使用 当v-if条件达成时才会渲染页面
//value 对象属性   key 属性值   index  索引
<li v-for="(value,key,index) in obj">{{value + "---" + key + "---" + index}}li>
data:{
	obj:{
		name:'zhangsan'
		age:20
	}
}
声明式编程

模板的结构和最终显示的结果基本一致

vue常用特性

表单的基本操作
  • input的单选框(radio) 和多选框(checkbox) 下拉框(select) 每个选项都要一个value属性来区分
    • input表单的单选项 的v-model 中的属性名的设为单个值
    • input表单的下拉框 的v-model 中的属性名的设为单个值
    • input表单的多选项 的v-model 中的属性名的值是一个数组
  • text和textarea的 v-model 中的属性名的设为单个值
  • submit 通过@click.prevent阻止默认行为并触发methods中的函数
表单域修饰符 .number .trim .lazy
  • number:将input输入的内容变为数字型的(默认是字符串型的)
    • 如果输入的值不能转换 会变成字符串型的
  • trim:将input输入的内容去除两边的空格
  • lazy: 将表单默认的input事件转换为change事件 ,input失去焦点的时候触发
<input  type="text" v-model.number="age"/>  输入内容的内容由 

自定义指令 全局指令Vue.directive

  • 使用的时候前面要加v-
    • inserted:指令插入标签中的时候触发其中的函数
    • bind:只调用一次
  • el为当前调用的DOM元素
  • 全局指令Vue.directive 可以在所有的Vue实例对象中使用
<input  type="text" v-foucs /> 
Vue.directive('foucs',{
	inserted: function(el) {
    	el.focus() //获取焦点方法
	}
})
局部指令
  • 局部指令只能在该Vue实例对象中使用
<input  type="text" v-color /> 
var vm = new Vue({
	el:'#app',
    directives:{
        color:function(el) {
            //el指当前使用这个指令的DOM元素
    		el.style.backgroundColor = 'red';   
		}
	}
})
自定义指令带参数
  • el:当前使用自定义指令的DOM元素
  • binding:一个对象 里面包含了一些自定义指令信息
    • value属性 :值为自定义指令传递的参数msg
    • name属性 :值为自定义指令名
<input  type="text" v-color="msg" /> 
var vm = new Vue({
	el:'#app',
	data:{
        msg:{
            color:'blue'
        }
    },
    directives:{
        //el指使用当前指令的input元素  
        color: {
			inserted:function (el, binding) {
				el.style.backgroundColor = binding.value.color;
            }
        }
	}
})
计算属性 computed
  • 将一些复杂的操作封装到这个属性中 类似函数封装
    • 计算属性是基于模型数据来进行处理
  • 再通过插值表达式{{自定义函数名称}} 来使用
  • 插值表达式调用时不要写小括号()
<div>{{reverseString}}</div>
data:{
    msg:'Hellow'
},
computed:{
	reverseString:function() {
        //这里的this指当前vue实例对象
		return:this.msg.split('')
	}
}
计算属性与方法的区别
  • 计算属性调用时会产生缓存,如果他所依赖的模型数据没有改变,他会从缓存中取出结果,可以节省CPU性能。
  • 而方法不会进行缓存,只要调用就执行一次。

侦听器 watch

  • watch 当数据监听的数据发生变化时就会调用其中的函数
  • function(val)中的参数val就是监听的属性的值
data:{
    msg:'';
},
watch:{
	msg:function(val) {
		console.log(val)
	}
}

全局过滤器和局部过滤器 filter

  • 全局过滤器Vue.filter
  • 过滤器和自定义指令一样 有全局过滤器和局部过滤器
  • 使用方式1:
    {{msg | 过滤器名称}}
  • 使用方式2:
//过滤器的使用
<div>{{msg | format}}</div>
//创建全局过滤器
Vue.filter('format',function(val){
    return value.charAt(0)
})
  • 局部过滤器filters
filters:{
	过滤器名称:function(val) {
		return value.charAt(0)
	}
}
携带参数的过滤器
  • 如果要携带多个参数可以传递一个对象过去比较好
<div>{{msg | format('yyyy-MM-dd')}}</div>
// val获得的是data中msg的值   arg获得的是format()小括号中的参数
Vue.filter('过滤器名称',function(val,arg){
    if (arg == 'yyyy-MM-dd') {
        return 处理业务逻辑
    }
})
生命周期(Vue实例的产生过程 )
  1. 创建(初始化)
    • beforeCreate Vue实例对象创建前调用
    • created Vue实例对象创建完毕调用
  2. 挂载(渲染视图)
    • beforeMount 在挂载开始之前调用
    • mounted 挂载完毕后调用
  3. 更新
    • beforeUpdate 数据更新时 调用
    • updated 数据更新完毕后调用
  4. 销毁
    • beforeDestroy 实例销毁之前调用
    • destroyed 实例销毁完毕调用
var vm = new Vue({
	el:'#app',
    data:{
        
    },
    mounted:function(){
        //挂载完毕后调用
    },
    beforeUpdate:function(){
        //数据更新时 调用
    },
    updated:function(){
        //数据更新完毕后调用
    }
})
Vue数组处理相关概念
  • 变异方法: push() pop() shift() unshift() splice() sort()排序 reverse()
    • Vue支持影响原数组的方法 响应式数据
    • 数组变化 视图会跟着变化
  • 非变异方法:filter()过滤 concat()组合 slice() 切片 findIndex()查询符合条件元素索引
    • 不影响原数组的方法 Vue不支持 响应式数据
    • 返回一个新数组 所以需要重新赋值给原数组才能修改
数组对象响应式处理
  • 不是初始化的数据,一般的DOM操作修改数组或对象的值无法做到响应式,解决方案:Vue提供给我们提供了一个set方法
  • Vue.set(vm.items,indexOfItem,newValue) 修改新增的数组元素或对象属性(实现修改后响应式视图)
    • 第一个参数 :实例data中的数组或对象名
    • 第二个参数 : 数组的索引 或 对象的属性名
    • 第三个参数 :修改后的值
  • 语法2:vm.$set(vm.items,indexOfItem,newValue)

组件化

组件的注册
  • data的值必须是个函数 ,每个组件的数据都是独立的 ,如果是对象 每个组件的数据都会共享.
  • template:组件模板必须是单个根元素, 不能是两个兄弟标签,可以单个父级标签包裹多个兄弟标签。
    • 可以使用模板字符串``
  • 组件的命名方式
    • 短横线 button-count 单词小写 单词之间用 - 分割
    • 驼峰命名 只能在模板字符串中使用 在中使用会出错
//全局组件的注册
Vue.component(组件名称,{
    data:function(){ return  {组件数据} },
    template:'组件模板内容',
    methods:{ 组件能调用的函数}
})
//定义一个名为button-counter的新组件
Vue.component('button-counter',{
    data:function() {
        return {
            count:0
        }
    },
    template:''
})
//使用
在页面要使用的地方插入  <button-counter></button-counter>

局部组件

  • 局部组件只能在父组件中使用,id=app的盒子中, 不能在全局组件中使用 超出了作用范围.
var vm = new Vue({
    el:'#app',
    components:{
        'component-a':{
            data:function(){
                return { msg:'zhangsan'}
            },
            template:'
demo
' }, 'component-b':{ data:function(){ return { msg:'lisi'} }, template:'
demo
' } } })
父组件向子组件传值
  • 在props属性中使用驼峰命名方式,模板中就要使用短横线的形式
    • 在组件使用时传递属性值,用短横线的方式传递到(父组件中调用时)
    • 在组件定义和模板字符串中 用驼峰命名
//父组件的V  
//parr为父组件传递的data属性的值   通过:p-arr将parr传递到props的pArr中 
//这样template可以通过props内的数据就可以使用父组件传递过来的值
<div id="app">	
	<component-a :p-arr="parr"></component-a>
</div>
//子组件的VM
Vue.component:(
	'component-a',{
        //props中的值 可以在子组件template中使用
        props:['pArr']
        //子组件
		template:'
{{item}}
' }, ) //父组件的VM var vm = new Vue({ el:'#app', data:{ parr:['apple','orange'] } })
子组件向父组件中传值
  • Vue父子组件通讯,遵循单向数据流
  • 只能父级对子级操作,子级不能直接对父级进行操作.
  • 子级要向父级进行操作,需要通知父级, 然后父级接到通知 自行修改操作
//父组件的V
<div id="app">	
    //2.@父组件监听子组件中的enlarge-text事件 ,当他触发时调用 父组件中的handle函数 
	<component-a :p-arr="parr" @enlarge-text="handle"></component-a>
</div>
//子组件的VM
Vue.component:{
	'component-a':{
        //1.点击时触发 $emit中设置的自定义事件
		template:'-text')">按钮'
	},
}
//父组件的VM
var vm = new Vue({
   el:'#app',
    methoeds:{
        handle:function() {
            console.log('子级发送请求 父级监听后自行修改')
        }
    }
})
子组件向父组件中传值携带参数
//父组件 通过$event接收传递过来的函数并作为实参给handle函数
<component-a :p-arr="parr" @enlarge-text="handle($event)"></component-a>
//子组件 $emit方法第二个参数可以给自定义事件传递参 多个参数可以使用数组或者对象传递
template:'-text',0.1)">按钮'
兄弟组件之间的数据交互
  1. var hub = new Vue() 创建事件中心
  2. hub.$on( ‘自定义事件名’ , 事件处理函数 ) 事件监听 (mounted挂载完毕时监听)
  3. hub.$emit(‘触发的兄弟组件监听的事件名’ , 传递的参数) 触发事件
  4. hub.$off(‘删除的自定义事件名’) 销毁事件
//1.创建事件中心hub
var hub = new Vue()
Vue.component('test1',{
    //data:function()可以简写为data()
    data:function(){
        return {
            uname:"zhangsan"
        }
    },
    //3.点击触发函数 
    template:`
	`,
    methodes:{
        //4.函数中触发兄弟组件中的事件 可以将自身的一些参数传递过去
        handle1:function() {
            hub.$emit('event2',this.uname)
        }
    },
    mounted:{
        // 2. 挂载完毕后监听事件 ,如果触发了就调用处理函数
        hub.$on('event1',(uname)=>{
    		console.log(uname)  //输出 lisi
		})
    }
})
Vue.component('test2',{
    data:function(){
        return {
            name:"lisi"
        }
    },
    //3.点击触发函数 
    template:`
	`,
    methodes:{
        //4.函数中触发兄弟组件中的事件 可以将自身的一些参数传递过去
        handle2:function() {
            hub.$emit('event1',this.uname)
        }
    },
    mounted:{
        // 2. 挂载完毕后监听事件 ,如果触发了就调用处理函数
        hub.$on('event2',(uname)=>{
    		console.log(uname) // 输出 zhangsan
		})
    }
})
//父组件中
var em = new Vue({
    methods:{
        //调用该函数时 销毁事件
        delete:function(){
            hub.$off('event1');
            hub.$off('event2');
        }
    }
})

插槽 slot

  • 在子组件中提供一个位置存放插槽
  • 父组件标签中的内容将显示在slot所在的位置
  • slot中可以填默认内容,如果父组件中没有填内容,将会使用默认内容
//父组件中
<mydiv>补充到插槽位置的内容mydiv>
//子组件中
Vue.component('mydiv',{
	template:`<slot name="header">如果父组件标签中没有填充内容,会使用插槽中的内容slot>`
})
具名插槽(用于多个插槽时)
  • 子组件中的slot 加一个name属性
  • 父组件的API添加slot属性值等于子组件的slot的name属性的值 即可匹配插槽
    • template 插槽内使用有多个标签要使用时用
//父组件中
<mydiv>
    	
    <template slot="header">
    填充到name属性值为header的插槽中,可以写多个标签,
    template>
mydiv>
//子组件中
Vue.component('mydiv',{
	template:`<slot name="header">如果父组件标签中没有填充内容,会使用插槽中的内容slot>`
})
作用域插槽
  • 父组件对子组件的内容进行加工处理

//父组件   slotProps可以获取子组件插槽中的所有属性的集合(是一个对象) 
<mydiv>
    <template slot-scope="slotProps">
        //当前循环的是id为2的数据时 添加高亮效果
        <strong v-if="slotProps.info.id==2" style="{color:blue}">{{slotProps.info.name}} 		strong>
    template>
mydiv>
//子组件
Vue.component('mydiv',{
	//此处省略一个if for循环
	<slot :info='item'>{{item.name}}slot>
})
  • slot-scope可以接收当前作用域的数据
异步进程回调地狱和Promise解决方案
  • 多层重复的异步进程进行嵌套,就叫回调地狱.
  • Promise本身是一个构造函数,要使用promise解决回调地狱的问题 需要使用new运算符创建Promise构造函数的实例对象
  • 在创建对象的时候需要传入一个匿名函数,匿名函数中有两个参数 resolve,reject
  • Promise实例对象方法:
    • then()方法 ,用于调用resolve函数
    • catch()方法也有个方法用于调用reject函数
    • finally()方法 成功与否都会执行(非标准)
  • 如果返回值是个普通值,自动转换成promise对象,并作为新promise对象的resolv
function p1() {
	return new Promise((resolve,reject) => {
		fs.readFile('./1.txt','utf8',(err.data) => {
			resolve(data)
		})   
	})
}
function p2() {
	return new Promise((resolve,reject) => {
		fs.readFile('./2.txt','utf8',(err.data) => {     //当文件读取的时候
			resolve(data)								//
		})   
	})
}
p1().then((r1) => {			//先调用p1函数
	console.log(r1)         //r1就是接收Promise的 函数resolve(data) 内的返回值data
	return p2();			//当第一个异步API读取完毕后 再返回包裹第二个异步API的函数调用
})
.then((r2) => {				//上一个函数返回了的调用链式链接了这个 可以达到依次执行的效果
	console.log(r2)			//r2就是接收Promise的 函数resolve(data) 内的返回值data
})  
promise对象方法
  • all 同时处理多个异步任务,所有任务都完成才能得到返回结果
  • rece 同时处理多个异步任务,只要有一个完成就返回结果,
promise.all([p1,p2,p3]).then(function(result){
	console.log(result)
})
promise.race([p1,p2,p3]).then(function(result){
	console.log(result)
})

Fetch

  • 更加简单的数据获取方式,功能更强大更灵活,可以看做xhr的升级版
  • 基于promise实现
fetch(url).then(data=>{
    //text属于fetch的一部分
    return data.text();
}).then(res=>{
    //res获得的才是服务器响应的实际数据
    console.log(res)
})
Fetch的get和delete请求参数
  • Restful的形式传参需要在路径后面带请求参数
fetch(url,{
    method:'get'
}).then(data=>{
    //text属于fetch的一部分
    return data.text();
}).then(res=>{
    //res获得的才是服务器响应的实际数据
    console.log(res)
})
Fetch的post和put请求参数
//json
fetch(url/请求参数,{
    method:'put',
    body:JSON.stringify({
        uname:'lisi',
        pwd:'123'
    }),
    headers:{
        'Content-Type':'application/json'
    }
})
//普通
fetch(url,{
    method:'post',
    body:'uname=lisi&pwd=123',
    headers:{
        'Content-Type':'application/x-www-form-urlencoded'
    }
}).then(data=>{
    //text属于fetch的一部分
    return data.text();
    	//响应json 数据用  data.json()
}).then(res=>{
    //res获得的才是服务器响应的实际数据
    console.log(res)
    	//响应json数据 需要res进行处理  console.log(JSON.parse(res))
})

axios的基本用法

  • 引入axios库文件
  • res 获取返回的一系列属性 .data获得服务器返回的内容
axios.get('请求路径')
    .then(function(res){
		console.log(res.data)
	})
axios的get和delete请求传参(delete方式和get基本一致)
  • 传统路径传参 (‘请求路径/传递参数’)
    • Restful路径传参 get(‘请求路径/:id’)
  • params属性传参
//路径传参
axios.get('请求路径/传递参数')
	.then(function(res){
		console.log(res.data)
	})
//params属性传参
axios.get('请求路径',{
    	params: {
            id:123
        }
	})
	.then(function(res){
		console.log(res.data)
	})
axios的post和put请求参数传递(put方式和pots基本一致)
  • json参数传递 自动转换为json格式参数
  • URLSearchParams 传递参数 自动转换为 &分割的 路径表单格式 参数
//json参数传递
axios.post('请求路径/:传递参数',{
    	uname:'zhangsan',
    	pwd:'123123'
	})
	.then(function(res){
		console.log(res.data)
	})

//通过URLSearchParams 传递参数(application/x-www-form-urlencoded) 
const params = new URLSearchParams()
params.append('uname','zhangsan')
params.append('pwd','123123')
axios.post('请求路径',params)
	.then(function(res){
		console.log(res.data)
	})
axios响应结果的属性 与全局配置
  • data : 服务器返回的实际数据
  • status 状态码
  • headers 响应头信息
  • statusText 状态码信息
axios.defaults.timeout = 3000; // 超时时间
axios.defaults.baseURL = 'http://localhost:3000/'; //默认地址
axios.defaults.headers['mytoken'] = '';     //设置请求头
axios拦截器
  • 请求拦截器 在发出请求之前配置一些信息
  • 思考:只拦截以什么什么路径开头的请求
axios.interceptors.request.use(function(config){
    return config;
},function(err) {
    //处理响应的错误信息
})
  • 响应拦截器 最先接收到响应结果 并可以配置一些信息
axios.interceptors.response.use(function(res){
    result res;
},function(err) {
    //处理响应的错误信息
})

async await 函数

async function() {
    const res = await axios.get('请求路径');
    return res;
}
console.log(res)

路由(资源列表)

  • 后端渲染(存在性能问题,不断刷新页面)
  • Ajax前端渲染(提高了性能,但不记录历史,无法前进后退)
  • SPA:基于URL的hash哈希值变化(不会触发新的url请求,并且能记录历史) 来触发Ajax改变页面的内容.
  • 前端路由:根据不同的用户事件,显示不同的内容,是实现SPA的核心技术 (用户事件与事件处理函数之间的对应关系)
根据哈希值hash(锚点#)实现简易的前端路由
  • 哈希值以#开头
  • 通过点击触发哈希值的变化, 监听事件中对哈希值的变化进行不同的页面内容显示
//监听哈希值的变化
window.onhashchange = function() {
    //获取当前网址中的哈希值#/zhuye   
    location.hash.slice(1)
}

Vue.Router的基本使用

  1. 引入 Vue 库文件 Vue.Router库文件

  2. 添加router-link路由链接

    
    <router-link to="/user">Userrouter-link>
    
  3. 添加路由占位符 (组件显示的位置)

    • or
    • 通过路由规则匹配到的组件会渲染到占位符所在的位置
  4. 创建路由组件 (填充到占位符的内容)

    var User = {
        template:`
    User
    `
    } var Register = { template:`
    Register
    `
    }
  5. 创建路由实例对象并设定规则

    //VueRouter是 库文件中的构造函数
    var router = new VueRouter({
        //所有路由的规则 
        routes:[
            //访问该hash地址时  占位符显示该对象内的组件 
            {path:'/user'.component:组件名称}
        ]
    })
    
  6. 挂载路由实例对象

    var vm = new Vue({
        el:'#app',
        router:router
    })
    
路由重定向redirect
  • redirect指定一个新的地址 ,实现重定向 (在规则中设置)
var router = new VueRouter({
    //所有路由的规则 
    routes:[
        //redirect重定向地址(一般用于设置默认显示页面)
        {path:'/',redirect:'/user'}
        {path:'/user'.component:组件名称}
    ]
})
路由嵌套 父级包含子级
  • 通过children 属性创建子路由规则
//配置嵌套组件
var Register = {
    template:`

Register


tab1 tab2 `
} var tab1 = { template:`

子组件 tab1

`
} var tab2 = { template:`

子组件 tab2

`
} //配置路由规则 var router = new VueRouter({ routes:[ //redirect重定向地址 {path:'/',redirect:'/user'} {path:'/user'.component:组件名称} //children 子路由规则也是一个规则 {path:'/register',component:register,children:[ {path:'/register',redirect:'/register/Tab1'} {path:'/register/Tab1',component: Tab1} {path:'/register/Tab2',component: Tab2} ]} ] })
动态路由匹配
  • 用于显示同样的页面 但是可以传递不同的id路径参数
    • 组件模板中可以通过$route.params获得路由参数
  • props属性值类型 (组件中通过props属性配置传递过来的对象属性名在模板中使用)
    • 值设为布尔值true 传递动态参数 route.params会被设置成组件属性
    • 值设为对象 传递静态参数
    • 值传递一个函数 返回值为一个对象 传递动态+静态参数
//路由规则设置了:id   /user/ 后面的路径会被当做参数 不同的参数也会显示同样的组件
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
const User = {
    //对应路由规则中的props属性中的
    props:['name','age','id'],
    template:`
{{id}}}
`
} var router = new VueRouter({ routes:[ { path:'/user/:id', component:User, props:route=>({ name:'zs', age:20, id:route.params.id })} ] })
命名路由
  • 可以给某个路由规则起一个别名,用于表示路由的路径
//routes路由规则中某一个规则添加user属性
{path:'/user/:id',name:'user',component:User}
//路由链接中  params传递路由参数
<router-link :to="{name:'user',params:{id:123}}">User</router-link>

编程式导航(常用于控制路由跳转)
  • 不同于a链接是html跳转 用js跳转就是编程式导航
//通过点击触发函数 使用编程式导航控制跳转页面
this.$router.push('/register')
//带查询参数   路径变为 /register?uname=zs
this.$router.push({path:'/register',query:{uname:'zs'}})

//在历史记录中前进1和后退-1  刷新0 
this.$router.go(1)
// 获取地址栏中的请求路径 例:/home
this.$route.path

模块化开发

  • 解决了命名冲突,文件依赖等问题,方便代码重用,便于维护.
  • 模块与模块之间相互隔离,需要特定了接口导入其他模块暴露的成员才能进行模块之间的交互.
  • 模块成员导出: module.exports 和exports
    • 默认导出只能使用一次
  • 模块成员导入: require(‘模块标识符’) 如果没有成员导入 接收一个空对象{}
  • 导入文件 import
//m1.js  暴露成员
export default {
    a,
    b,
    show
}
//import  导入成员
import m1 form './mi.js'
按需导出和按需导入
  • 按需导出可以使用多次
//m1.js  按需导出,
export let c = 1;
export let d = 2;
//index.js中    import按需导入
import m1,{ c , d} form './mi.js'
console.log(c,d)
//用as给导入的c起别名 c1
import { c as c1} form './mi.js'
直接导入并执行
//m2.js 中
console.log('直接导入')
//index.js中   直接执行模块中的代码
import './m2.js'

webpack(打包工具)

  • 前端项目构建工具
  • 提供了友好的模块化开发支持,具有代码混淆,处理兼容性问题,性能优化等功能.
webpack基本使用
  • 使用npm init -y 安装项目描述文件
  1. 安装 : npm install webpack webpack-cli -D //-D 放入开发依赖中

  2. 在项目根目录中创建 webpack.config.js 的配置文件

    module.exports = {
        mode:'development'     
    

}


3. 在package.json配置文件中scripts节点下 新增sev脚本

```js
"scripts":{
    "dev":"webpack" //节点下的脚本 可以通过 npm run执行
}
  1. 在终端运行 npm run dev命令 启动 webpack 进行项目打包

  2. 将script文件路径 改为打包好的文件路径

    //dist为webpack帮我们创建的文件夹
    <script src="../dist/main.js">script>
    
webpack的配置
  • mode :指定构建模式(打包模式)
    • development : 项目开发模式(项目依赖) 不会进行压缩 速度更快可以进行代码查看
    • production : 产品发布模式(开发依赖) 会进行压缩和混淆
  • entry : 设置入口文件 (要打包的文件,使用绝对路径)
  • output : //设置文件输出路径和文件名 (打包好的文件,使用绝对路径)
    • path : 设置输出路径目录
    • filename : 设置输出后的文件名
  • plugins : 插件列表
//引入系统路径模块
const path = require('path')
module.exports = {
    // 指定构建模式
    mode:'development',
    //设置入口文件(要打包的文件)
    entry:path.join(__dirname,'./src/index.js'),
    //设置文件输出路径和 文件名(打包好的文件)
    output:{
        path:path.join(__dirname,'./dist'),
        filename:'bundle.js',
    },
    plugins:[htmlPlugin]
}
webpack自动打包
  1. 自动打包安装: npm i webpack-dev-server -D
  2. 打开package.json 更改 script配置 “dev” : “webpack-dev-server”
  3. 将src>index.html中 script标签引用路径 改为 “/bundle.js”
  4. 运行 npm run dev 命令重新打包 (类似NodeJS的nodemon app.js)
  5. 在服务器中通过 http://localhost:8080地址 查看打包效果
  • webpack-dev-server 会启动一个实时打包的http服务器
  • webpack-dev-server 自动打包生成的输出文件 ,是放在项目根目录的,而且是虚拟的看不见的,只能通过http://localhost:8080/bundle.js方式打开
  • 配置自动打包参数
    • open 自动打开浏览器
    • host 配置 IP 地址
    • port配置端口号
"dev" : "webpack-dev-server --open --host 127.0.0.1 --port 8888"
配置html-webpack-plugin 生成预览页面
  1. 安装插件: npm i html-webpack-plugin -D

  2. 修改webpacke.config.js 头部文件

    //引入模块
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const htmlPlugin = new HtmlWebpackPlugin({
        template:'./src/index.html',
        filename:'index.html'
    })
    module.exports = {
        plugins:[htmlPlugin]
    }
    

webpack中的加载器(loader)

  • webpack 只能打包 .js的文件
  • loader 协助webpack打包
  • 判断是否是.js文件
    • yse 判断是否是高级js语法(es6es7)
      • yes 判断是否配置了 babel
        • yes 调用 loader处理
        • no 报错
      • no webpack处理
    • no 判断是否配置了对应的loader
      • yes 调用 loader处理
      • no 报错
  1. 打包处理css文件

    • npm i style-loader css-loader -D 安装处理css文件的loader
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    //存放loader规则
    module:{
        rules:[
            {test:/\.css$/,use:['style-loader','css-loader']}
        ]
    }
    
    • test 正则 以什么结尾
    • use对赢要调用的loader
      • use中的loader顺序是固定的
      • 调用顺序是从后往前的
  2. 打包处理less文件

    • npm i less-loader less -D 安装处理css文件的loader
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    {test:/\.less$/,use:['style-loader','css-loader','less-loader']}
    
  3. 打包处理scss文件

    • npm i sass-loader node-sass -D 安装处理sass文件的loader
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    {test:/\.scss$/,use:['style-loader','css-loader','sass-loader']}
    
  4. 配置postCSS 自动添加 css 兼容性前缀

    • npm i postcss-loader autoprefixer -D
    // 创建postcss.config.js 中
    const autoprefixer = require('autoprefixer')
    module.exports = {
        //挂载插件
        plugins:[autoprefixer]
    }
    // webpack.config.js 中  module   配置loader 
    {test:/\.css$/,use:['style-loader','css-loader','postcss-loader']}
    
  5. 打包样式表中的img图片和字体文件

    • npm i url-loader file-loader -D
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    {test:/\.jpg|png|gif|bmp|ttf|eof|svg|woff|woff2$/,use:'url-loader?limit=19640'}
    
    • ?后面是loader的参数项
    • limit用来指定图片的大小,单位是字节(byte),小于limit大小的图片,会被转为base64图片(读取会更快)
  6. 打包处理js中的高级语法(es6 es7)

    • npm i babel-loader @babel/core @babel/runtime -D 安装babel转换器相关的包
    • npm i @babel/preset-env @babel/piugin-transform-runtime @babel/plugin-proposal-class-properties -D 安装babel语法插件相关包
    • 在根目录 创建babel 配置文件 babel.config.js 并初始化
    module.exports = {
        presets : ['@babel/preset-env'],
        plugins : ['@babel/plugin-transform-runtime','@babel/plugin-proposal-class-			properties']
    }
    
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    {test:/\.js$/,use:['babel-loader'],exclude:/node_modules/}
    
    • exclude : 排除项 里面填正则表达式 不会打包这个文件夹
  7. vue 组件加载器

    • npm i vue-loader vue-template-compiler -D
    • 在webpack.config.js 的module 的rules数组中 添加 loader规则
    const VueLoaderPlugin = require('vue-loader/lib/plugin')
    
    {test:/\.vue$/,loader:'vue-loader'} 
    
    plugins:[new VueLoaderPlugin()]
    

单文件组件

  • 后缀名为vue的文件

  • 可以解决

  • 需要配置对应的loader文件

  • template 定义模板内容

  • script 业务逻辑

  • style 样式区域

    • scoped 防止各组件样式冲突问题
<template>
	<div>
        <h1>
            这是App根组件
        h1>
    div>
template>
<script>
export default {
    data() {
        return
    }
}

script>
<style scoped>

style>
在webpack中使用vue
  1. npm i vue 安装vue
  2. src > index.js 入口文件中 ,通过 import Vue from ‘vue’ 来导入vue构造函数
  3. 创建vue实例,并制定要控制的el区域
  4. 通过render 函数渲染app根组件
 import Vue from 'vue';
import App from './components/App.vue'

const vm = new Vue({
    el:'#app',
    render : h => h(App)
})

webpack打包发布
  • 在package.json文件中配置webpack打包命令
  • 该命令默认加载项目根目录中的 webpack.config.js 配置文件
"script" : {
    //用于打包的命令 
    "build" : "webpack -p",
    //用于开发调试的命令
   	"dev" : "webpack-dev-server --open --host 127.0.0.1 --port 8888"
}
  • 使用 npm run build打包 (可以先将dist文件删除)

Vue 脚手架

  • 快速生成vue基本架构
  • 安装3.x版本的vue脚手架 npm install -g @vue/cli
    • vue -V 查看vue脚手架 版本号
    • 3.x支持高版本也支持低版本基本架构
创建新版vue项目
  1. 基于 交互式命令行 创建 vue create 项目名

  2. 基于 图形化界面 的方式 创建 vue ui

  3. 基于 2.x的旧模板 创建 旧版vue项目(了解)

    1. npm install -g @vue/cli-init
    2. vue init wepack my-project
脚手架项目自定义配置
  • 在项目根目录创建 vue.config.json
module.exports = z{
    devServer = {
        "port":8888,
        "open":true
    }
}
Element-UI(命令行方式安装)
  • 一个基于vue2.0的组件库
  • 官网: http://element-cn.eleme.io/#/zh-CN
  1. npm i element-ui
  2. 导入Element-UI相关资源
//导入组件库
import ElementUi from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Element-UI(图形化界面安装)
  • vue ui命令打开 图形化界面
  • 通过Vue项目管理器 ,进入具体的项目配置面板
  • 点击插件 > 添加插件 ,进入插件查询面板
  • 搜索 vue-cli-plugin-element 并安装

Vue项目初始化步骤

  1. 安装Vue脚手架 npm install -g @vue/cli (全局安装 安装一次就不用再安装了)
  2. 通过Vue脚手架 创建项目 Vue ui
  3. 使用码云将项目上传到远程仓库
  4. 安装备份MySQL数据库 并导入数据库启用
  5. 安装服务器相关依赖包, 启动服务器 并使用PostMan测试路由接口
ESLint语法报错问题
  • 项目根目录创建 .prettierrc 文件
{
     "semi":false, // semi 格式化 末尾不会额外加分号
     "singleQuote":true // 格式化 启用单引号
}
  • 空格报错 打开.eslintrc.js 文件 rules对象中添加一条属性 (需要重新编译项目)
rules:{
    'space-before-function-paren' : 0
}

Vuex

  • 集中管理共享数据
  • 解决了复杂的组件之间关系的数据传递
  • 存储的数据是响应式的
  • 易维护
Vuex的使用
  • npm install vuex --save
// main.js 配置
import store from './store/index'
new Vue({
  store,
  router,
  render: h => h(App)
}).$mount('#app')
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
    //state中存放的就是全局共享数据
  state: {
    count: 0
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }		
})
state数据引用方式
//第一种
{{$store.state.count}}
//第二种引用方式(可以避免组件内直接对共享数据进行操作)
{{count}}
//script
import { mapState } from 'vuex'
computed: {
  ...mapState(['count'])
}
Mutation
  • 修改state中的数据
  • 不要执行异步操作
//store/index.js中
mutations: {
    add (state) {     //不带参数
      state.count++
    },
    minus (state, step) {    //带参数  形参只能有两个 
      state.count -= step
    }
  }

//组件中使用  this.$store.commit('函数名', 2)   2为传递的参数
methods: {
  minus () {
    this.$store.commit('minus', 2)
  }
}

//第二种方式 先引入
import { mapMutations } from 'vuex'

methods: {  
  ...mapMutations(['minus']),
  //点击按钮触发事件    
  minus () {
    //   mapMutations中定义的
    this.minus(2)   //传递的参数写在括号内
  }
}
action
  • 用于进行异步操作(规范)
  • Mutation中使用异步操作 vue tools插件监听不到数据的变化
  • 回调中使用commit触发 Mutation 修改数据
// 定义
actions: {
  addAsync (context) {
    setTimeout(() => {
      context.commit('add')   //调用Mutation中的 add函数
    }, 1000)
  }
}
//组件 函数中
addAsync () {
  this.$store.dispatch('addAsync')
}
//携带参数action
actions: {
  addAsync (context, step) {
    setTimeout(() => {
      context.commit('add', step.num)   //调用Mutation中的 add函数
    }, 1000)
  }
}
//携带参数 组件 函数中
addAsync () {
    //为了避免action传多个参数会undefined的情况,把所有变量装到一个对象里传过去
  this.$store.dispatch('addAsync', { num: 5 }) 
}



//action第二种调用方式
minusAsync (context, step) {
  setTimeout(() => {
    context.commit('minus', step.num)
   }, 1000)
 }
//引入
import { mapActions } from 'vuex'
//函数中映射为自己的函数
methods: {
  ...mapActions(['minusAsync']),
}
//调用
<button @click="minusAsync({ num: 3 })"> -N</button>
getters
  • 对已有state数据进行包装 不会修改其数据 类似Vue中的计算属性
// store中定义
getters: {
  showNum: state => {
    return '当前count的最新值是【' + state.count + '】'
  }
}
//组件中使用 
{{this.$store.getters.showNum}}

// 使用方式二
import { mapGetters } from 'vuex'
computed: {
    ...mapGetters(['showNum']
}
Vue登录退出功能
  1. 处理好分支状态 并创建 登录子分支
  2. 梳理项目结构
    • vue ui
    • 任务> 运行 serve > 启动app(查看项目效果)
    • 将不需要的结构删除
  3. 创建login.vue单组件
    • 在主页中设置路由占位符
    • 在路由js中配置login的路由 (并设置重定向访问/的时候直接访问login单组件页面)
    • 搭建静态页面html 和css
      • 由于使用的是less语法 需要 在element ui中 下载 less-loader 和 less 依赖
    • https://element.eleme.cn 进入element官网复制需要的组件进行使用
      • 由于安装的element是按需导入
      • 所以每个组件要在element.js中导入进来
      • 同时通过 Vue.use(组件名) 开放到整个项目
  4. 数据绑定
    • data中定义return 对象属性:数据对象 loginForm
    • 在表单上绑定自定义属性 :model=’ loginForm’
    • 表单控件上添加 v-model=’ loginForm.属性名’
  5. 路由规则
  • data中定义return 对象属性:路由规则对象 loginFormRules
  • 在表单上绑定自定义属性 :rules=’ loginForm’
  • 在对应的表单控件的盒子form-item 添加 prop属性 值为 loginFormRules.对应的路由规则
  1. 重置功能
    • 表单添加一个 ref属性 值为实例对象名称
    • 表单内的控件 的this 会添加一个 $refs属性
    • 通过this.$refs.自定义ref属性值 就可以拿到表单的实例对象了
    • 再通过element的表单控件方法 resetFields 就可以重置整个表单了
  2. 预验证
    • 通过ref属性添加表单调用对象
    • 通过表单调用对象方法 validate 可以获取验证结果(布尔值)
  3. 配置axios发送登录请求
    • 在main.js中引入axios 并全局配置axios默认地址
    • 在Vue原型对象上添加 axios 这样所有组件中都可以通过this 来访问axios
    • 查看接口文档 在表单预验证通过后 发送ajax请求
    • 接收返回值并做响应的处理
  4. 全局弹窗组件Message
    • element中引入Message
    • 在Vue的原型对象上挂载Message
    • 组件中通过 this 可以访问挂载上去的message方法
  5. 登录保持 token
  • 将服务器返回的数据中的token属性 放入sessionStorage中
  • window.sessionStorage.setItem(‘token’, res.data.token)
  • 并通过this.$router 重定向到home页面
  • 创建home.vue并搭建基本结构 在router.js中引入并配置路由
  1. 路由导航守卫/登录拦截
    • 在router.js中 使用路由的对象的方法 beforeEach((to, from, next) =>{})来设置登录拦截
    • to将要访问的页面路径 from 从哪个页面路径跳转而来 next放行函数
    • 当window.sessionStorage中没有token属性时 next(’/login’) 强制跳转到登录页面
    • 当访问登录页面和 sessionStorage中由token属性时 则next() 放行
  2. 退出登录
    • 添加按钮触发函数
    • window.sessionStorage.clear() 删除token
    • this.$router.push(’/login’) 重定向登录页面
  3. 提交代码到码云远程仓库
    • git add . 提交代码到缓存区
    • git commit -m “完成了登录功能” 提交代码
    • git checkout master 切换到主分支
    • git merge login 合并(更新) 登录分支
    • git push 上传代码到远程仓库
    • git checkout login 切换到登录分支
    • git push -u origin login 将登录分支上传到远程仓库 并命名为login分支
Vue用户列表功能实现
  1. element 寻找适用 container容器组件 搭建home.vue文件基本结构
    • element.js中引入对应的element组件
    • Vue.use 开放到所有组件中
  2. 通过axios请求拦截器添加token
    • main.js中 在将axios添加到请求头之前 创建一个请求拦截器
    • 请求拦截器中 为请求头添加一个后台要求的属性 并赋值token
  3. 获取左侧菜单数据
    • created vue实例对象创建完毕时调用一个函数
    • 函数中 通过axios请求获取左侧菜单数据
    • data中创建一个数组 存放获取的左侧菜单数据
  4. 渲染左侧菜单
    • 利用双重v-for 渲染左侧菜单
    • 外层和内层的 当前循环元素 item 不能一样
    • index 需要设置不同的值 不然会同时展开 可以设置为传递过来的id
  5. 分类图标
    • data中创建一个图标对象
    • 图标的键设为 对应数据的id 值 设置对应的图标字符串
    • :class=“图标对象[循环体.id]”
  6. 每次只打开一个菜单
    • el-menu标签添加 unique-opened 属性
  7. 侧边栏折叠与展开
    • 创建一个按钮用于折叠与展开
    • 创建一个值为布尔值的data属性 (展开与折叠开关)
    • 点击按钮时触发函数 取反开关属性布尔值
    • 属性绑定用于折叠与展开的属性 并将开关属性作为值
  8. 首页路由重定向
    • 创建welcome.vue 并搭建基本结构 router.js中引入
    • 在el-main中位置设置一个路由占位符
    • 路由占位符在/home中 所以 /home路由要嵌套新路由作为子路由 并重定向到这个子路由
  9. 侧边栏路由链接改造
    • el-menu 添加router 属性 表示开始路由模式
    • :index 绑定的属性应改为服务器传递过来的path路径 由于没有/ 所以前面要加一个/
  10. 路由展示用户列表页面
  • 创建 users.vue 并搭建基本结构 router.js中引入
  • 由于替换掉的是welcome.vue页面
  • 所以在welcome同级创建路由即可
  1. 侧边栏激活状态
  • 侧边栏展开是依靠index值的
  • 点击时将对应的index值存入sessionStorage 中
  • 当页面实例创建完毕时将sessionStorage中的值 赋值给 一个容器
  • 菜单激活状态属性 default-active 的值 使用容器的值
  1. 绘制用户列表组件基础布局结构
  • 利用 面包屑 卡片 input 和 栅格系统layout分栏间隔布局
  1. 获取用户列表参数
  • 在created创建好实例对象时 调用函数发送ajax请求获取用户列表参数
  • 并将用户列表数组和当前页码存入data数据
  1. 使用el-table组件渲染基本用户列表
  • el-table 的:data 属性中 放数据中的用户列表数组
  • el-table-column 的prop属性中 放数组中循环对象的属性名 label属性中输入表头名称
  • 索引列 用el-table-column 只设置type属性 值为index
  1. 自定义状态列的显示效果
  • 状态栏中创建一个template 并设置属性slot-scope 获取作用域插槽中的所有数据
  • 通过slot-scope设置的名字 .row 获取当前行所有数据
  • 再用el-switch双向数据绑定v-model 设置布尔值来实现开关状态
  1. 通过作用域插槽渲染操作列
  2. 实现分页效果
  • 利用pagination组件实现分页效果
  1. 修改用户状态
  • 为开关添加@change事件 并将 slot-scope当前行的所有数据传递到函数中
  • 函数中发送请求修改用户状态数据
  1. 实现搜索功能
  • 为搜索按钮添加点击事件调用之前设置 的获取用户列表函数即可
  1. 渲染用户的对话框
  • 使用dialog 组件
  1. 渲染添加用户的表单
  • 在dialog 组件 中 嵌套 form组件即可
  • form属性绑定 :rules 可创建 路由规则对象设置规则
  • form-item 添加 prop 可以匹配对象规则中的 属性名的规则
  1. 自定义校验规则
  • data中创建校验规则 (rule,value,cb)=> {} 在其中定义正则的处理代码
  • value为当前表单内容 cb为回调函数
  • 在对应规则属性中 {vailddator: 创建的校验规则 , trigger : ‘blur’} blur 失去焦点触发
  1. 表单关闭后重置表单
  • 通过表单引用对象 的方法resetFields()
  1. 添加用户
  • 通过表单引用对象方法 validata判断表单预验证通过没
  • 通过了 发送ajax请求 接收返回值
  • 未成功 return 提示信息
  • 成功则关闭对话框并调用获取用户列表数据
  1. 修改用户
  • 创建点击事件 创建修改用户对话框
  • 点击事件中 发送请求获取用户数据 显示在对话框中 并数据校验
  • 创建提交点击事件 效验成功时 发送请求并将表单内的数据作为请求参数
  • 修改不成功则return 并提示 修改成功则删除对话框 并更新数据
  1. 删除用户
  • 添加点击按钮删除事件并将id传递过去
  • 根据ID 发送请求 接收返回值
  • 失败 return 错误提示 成功 刷新用户数据列表
  1. 创建user子分支并提交到远程仓库
  • git checkout -b user 切换到-b 新建的user分支上
  • git add. 提交代码到暂存区
  • git commit -m “完成用户列表功能” 提交代码到本地仓库
  • git push -u origin user 提交代码到远程仓库 新建的user分支
  • 由于代码都切换带到user分支了 所以 master 还是上次提交login分支的进度
  • git checkout master 切换到主分支
  • git merge user 合并user分支代码
  • git push 上传到远程仓库更新 master主分支代码
Vue权限管理功能
  1. 创建rights权限分支
    • git checkout -b rights 切换并创建rights分支
    • git push -u origin rights 在远程仓库新建rights分支 并将当前进度提交上去
  2. 创建权限列表页面并渲染
    • 创建rigets.vue 并添加路由
    • 使用 面包屑 卡片 表格组件搭建页面基本结构
    • 创建获取权限列表信息函数 并赋值给存放数据的模板数据
    • 页面搭建完毕时调用获取权限列表函数
    • 表格中根据 模板数据渲染表格信息
  3. 创建角色列表页面并渲染
    • 创建roles.vue 并添加路由
    • 和权限列表基本一致
    • 表格第一列为展开列 里面为权限分配展示
    • 使用三重v-for数据渲染 使用分栏间隔布局
  4. 添加角色
    • 创建添加角色对话框 并在里面放入一个Form表单并双向绑定一个数据模板 表单通过绑定rules和porp属性进行表单验证
    • 点击按钮触发函数弹出对话框
    • 点击确认触发函数 先使用表单引用对象的validate属性判断是否通过预验证 再发送ajax请求添加角色
    • 添加成功后 关闭对话框 并调用函数刷新角色列表
    • 为form表单绑定colse事件 对话框关闭时触发函数 清空在对话框中使用过的双向绑定的数据模板
  5. 删除角色
    • 点击按钮触发函数并通过作用域函数slot-scope 将当前行的数据传递到删除角色函数中
    • 函数中弹出confirm组件 当用户点击确认后 根据传递过来的ID发送请求删除角色 并调用函数刷新角色列表
  6. 编辑角色
    • 创建编辑角色对话框 在里面放入一个Form表单并双向绑定一个数据模板 表单通过绑定rules和porp属性进行表单验证 设置一个数据模板存储当前角色id
    • 点击按钮触发函数弹出对话框
    • 点击确认触发函数 先使用表单引用对象的validate属性判断是否通过预验证 再根据数据模板中的角色id发送ajax请求编辑角色
    • 编辑成功后 关闭对话框 并调用函数刷新角色列表
    • 为form表单绑定colse事件 对话框关闭时触发函数 清空在对话框中使用过的双向绑定的数据模板
  7. 删除角色下制定权限
    • 为标签添加closable属性可提供一个x按钮
    • 创建close事件 关闭tag标签时触发删除权限函数 并将当前行的数据和当前权限ID传递过去
    • 函数中使用弹框组件 当点击确认时 调用接口删除对应id权限
    • 由于重新调用接口获取数据会关闭扩展列 所以 将服务器传递过来的新数据赋值给 当前行数据(传递给函数的当前行数据)
  8. 弹出分配权限对话框
    • 创建分配权限对话框 点击时将对话框开关改为true打开
    • 同时调用函数 获取所有权限列表信息 (使用tree类型) 保存在数据模板中
    • 在对话框中使用tree组件 根据数据模板渲染 tree组件
  9. 分配权限默认勾选
    • tree组件中 添加树组件勾选框和 默认展开全部属性
    • 再添加勾选框绑定id属性 和根据数组默认勾选 勾选框属性
    • 点击展开分配权限对话框函数中 调用递归函数 将本行数据 和 一个用于存储 勾选id的模板数据传递进去
    • 递归函数中 判断是否有childeren属性 来确认是否是第三级权限对象 当是第三级时 将当前形参的id push添加到 模板数据中的数组中 并return 返回
    • 当不是第三级权限时 循环当前数据形参的children数组 调用该递归函数并将当前循环项和 存储id模板数组传递进去
  10. 调用API分配角色权限
  • 使用 tree 两个方法获取 全选 和半选 勾选框所对应权限ID
  • 根据 ID 发送 ajax 请求 接收返回值 逻辑处理 后 重新获取角色列表信息
  1. User页面用户分配角色
    • 创建一个带有下拉框的分配角色对话框
    • 点击分配按钮将当前行数据传递到 显示分配角色对话框函数中,并将当前行的数据渲染到对话框,同时发送请求获取所有角色数据并渲染到下拉框中
    • 下拉框中将 角色的id设为 模板数据 点击提交时 使用当前用户id和选择角色id发送请求分配角色
    • 服务器返回数据逻辑判断成功时 重新获取用户列表数据并将对话框关闭
  2. 提交角色列表功能分支
    • git add . 将当前rights分支代码提交到缓存区
    • git commit -m “提交信息” 将缓存区代码提交到本地仓库
    • git push 将本地仓库上传到远程仓库中
    • git checkout master 切换到主分支
    • git merge rights 合并新完成的子分支
    • git push 再将主分支的代码更新到远程仓库中
Vue商品分类功能
  1. 新建 商品分类分支
  • git checkout -b goods 切换并新建商品分类分支
  • git push -u origin goods 将新分支同步到远程仓库中
  1. 创建goods.vue 页面
  • 搭建页面基本结构 并配置路由
  • 添加 面包屑 卡片组件 和 添加分类按钮
  1. 商品分类列表数据渲染
  • vue实例化函数中 调用获取商品列表数据函数 将获取的商品列表数据保存在数据模板中
  • 使用table 组件的树形数据模式 在:data属性值中放入商品列表数据数组 row-key属性值 中放入每个数据的id属性名 :tree-props中的children属性值中放入子数组名
  • table-column 列的属性中 label 为表头 prop 放入当前数据的属性名
  • 是否有 和 排序 和操作 使用 作用域插槽 放入 自定义组件 并根据 slot-scope 获取当前行数据 渲染组件
  1. 添加商品分类
  • 创建添加分类对话框 点击添加分类时弹出对话框
  • 创建form表单 并创建 添加分类 输入框 并双向数据绑定 一个用于发送ajax请求的数据模板
  • 调用函数 获取所有父级分类数据 并保存在数据模板中
  • 使用Cascader 级联选择器组件 渲染所有父级分类数据
    • options 值为所有父级数据模板
    • props 在数据模板中定义一个对象
      • value 属性值为选中的属性
      • label 显示的值为选中的属性
      • children 子级数组根据哪个属性渲染
    • v-model 双向数据绑定 选中的数据 在数据模板中创建这个数组
  • 使用 @change事件 当选中某个选项时触发 当数据模板中用于存放选中数据的数组长度大于0时 说明有数据 将 数组中的最后一项 和 当前数据所在层级(数组长度) 保存在用于添加分类的数据模板中
  • 点击确认时通过表单引用对象预验证表单
  • 通过后 发送请求 添加分类 返回status 为正确时 调用函数刷新商品分类列表 并 关闭对话框
  1. 提交商品分类模块
  • git add . 提交代码到缓存区
  • git commit -m “提交信息” 保存到本地仓库
  • git push 上传到远程仓库
  • git checkout master 切换主分支
  • git merge goods 合并新完成的代码
  • git push 上传到远程仓库的主分支
Vue 商品管理 分类参数 功能
  1. 创建 goods_params分支
    • git checkout -b goods_params 新建分支
    • git push -u origin goods_params 同步到远程仓库
  2. 搭建goods_params基本结构
    • 创建goods_params.vue 页面 并在router 路由中设置路由规则
    • 搭建goods_params 基本骨架 并创建面包屑导航和 card卡片区域
    • 添加一个警告组件 用于提示用户操作
  3. 渲染商品分类的级联选择框
    • 页面实例创建完毕函数中 调用函数获取所有商品分类数组并保存在数据模板中
    • 创建cascader组件并进行配置
      • options 渲染的数据数组
      • props 渲染的数据配置对象
        • value 选中值的id
        • label 显示对应的数据名
        • children 渲染子级数组名
        • expandTrigger 展开子级的方式
      • @change 选中状态发生改变时触发的函数
  4. 渲染动态参数和静态属性区域
    • 引入Tabs标签页组件 根据name 显示不同页面
    • 每个tab-pan标签中添加一个用于添加数据的按钮 和一个渲染数据的表格
    • 在级联选择器选中时@change事件和 标签页切换时@tab-clic事件的触发函数中 调用获取参数的函数
      • 根据级联选择器选择的数据长度判断是否选中了第三级数据 再 根据标签页的name 属性值 来判断当前在时在动态参数页还是静态属性页
      • 获取以上两点成立的数据 发送请求 获取数据 并保存在不同的数据模板中
    • 表格中根据获取的数据来渲染 动态参数页和 静态属性页
  5. 添加动态参数 和静态属性
    • 创建添加对话框 点击按钮时触发 (两个按钮共用一个函数)
    • 根据 标签页的v-model选中属性值 来渲染对话框
    • 对话框中创建表单 并设定验证规则 对话框关闭函数中 利用引用对象情况表单的内容
    • 点击确认触发函数 通过引用对象预验证表单 通过后 根据 数据模板中的 输入框的值 和 标签页所在页name的值 发送请求添加数据 路径中的当前分类id 可以在计算属性中获得
    • 添加成功后 调用函数重新获取数据列表 并关闭对话框
  6. 修改动态 或静态属性
    • 创建添加对话框 根据 标签页的v-model选中属性值 来渲染对话框
    • 点击按钮时触发函数函数显示对话框 (两个按钮共用一个函数) 并将当前行的数据传递进去
    • 函数中根据传递过来的当前行数据保存当前参数id 为输入框的双向绑定数据 赋值参数名
    • 对话框中创建表单 并设定验证规则 对话框关闭函数中 利用引用对象情况表单的内容
    • 点击确认触发函数 根据数据模板中的数据和计算属性的第三级数据id发送请求 修改数据
    • 修改完成后 关闭对话框并刷新数据列表
  7. 删除动态 或静态属性
    • 点击触发函数 并将当前行参数id传入函数中
    • 函数中使用$comfirm显示确认弹框
    • 点击确认时 根据计算属性的第三级数据id和参数id发送请求删除数据
  8. 渲染参数下的可选项
    • 为表格添加一个扩展列 扩展列中使用 作用域插槽嵌套标签组件
    • 当级联选择器选中和 标签页变动 触发的函数内 根据作用域插槽传递过来的id 获取 可选项 数据
    • 利用v-for 渲染tag组件内容 并且 数据模板挂载在当前作用域下 可以使每个作用域都是独立的
    • input输入框 可以使用this.$nextTick() 回调 让输入框自动获取焦点
    • 使用动态编辑标签 当触发回车和失去焦点事件时 将 输入框的内容 添加到当前作用域的标签数据数组中 并根据数组发送请求添加标签接选项 添加完成后 清空输入框内容 并 关闭输入框
  9. 删除可选项
    • 标签组件关闭事件中 将索引 和当前行数据传递给关闭事件函数
    • 函数中 使用$comfirm 确认用户是否确认删除
    • 确实后根据传递过来的数据 发送请求 删除可选项
  10. 提交商品分类参数模块
  • git add . 提交代码到缓存区
  • git commit -m “提交信息” 保存到本地仓库
  • git push 上传到远程仓库
  • git checkout master 切换主分支
  • git merge goods_params 合并新完成的代码
  • git push 上传到远程仓库的主分支
Vue商品列表功能
  1. 创建list权限分支

    • git checkout -b goods_list 切换并创建rights分支
    • git push -u origin goods_list 在远程仓库新建rights分支 并将当前进度提交上去
  2. 搭建页面基本结构

    • 创建list.vue页面 并配置路由
    • 搭建 面包屑 卡片 搜索表单组件
  3. 渲染商品数据列表

    • 创建表格组件
    • 创建获取列表数据函数 并配置数据模板 在created 页面实例化函数中 调用
    • 将获取的列表数据保存在数据模板中 并使用表格组件 渲染表格
  4. 自定义全局过滤器

    • main.js中配置
    Vue.filter('dateFormat', function(originVal) {
      const dt = new Date(originVal)
      const y = dt.getFullYear()
      const m = (dt.getMonth() + 1 + '').padStart(2, '0')
      const d = (dt.getDay() + '').padStart(2, '0')
      const hh = (dt.getHours() + '').padStart(2, '0')
      const mm = (dt.getMinutes() + '').padStart(2, '0')
      const ss = (dt.getSeconds() + '').padStart(2, '0')
      return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
    })
    
    • 表格中通过作用域插槽 {{当前行渲染数据 | dateFormat}} 使用过滤器
  5. 实现分页效果

    • 利用pagination组件实现分页效果
  6. 搜索和删除商品

    • 为搜索输入框双向数据绑定 商品列表的数据模板
    • 当点击输入框时调用获取商品列表函数即可
    • 为删除按钮添加作用域插槽和点击事件
    • 点击事件触发函数并将当前行的商品id传递给函数
    • 函数中通过商品id发送请求删除商品 并重新获取商品列表
  7. 添加商品

    • 点击添加商品按钮 创建添加商品页面和路由 跳转至添加商品页面
    • 渲染页面基本机构 并引用步骤组件 和标签页组件
    • 将步骤组件的active属性 和标签页显示的v-model 的值设为同样的索引 即可达到联动效果
    • 创建级联选择器 页面加载时请求获取分类数据 渲染级联选择器
    • 使用标签页before-leave回调 当前索引变化时 选择的分类数据数组长度不等于3就返回false阻止标签页切换
    • 使用标签页点击事件 当点击商品参数标签页时 发送ajax请求 获取商品动态参数
    • 商品参数标签页引用多选组组件 由于vals属性是字符串 获取动态参数的返回值数组要使用循环并将vals属性通过split(’ ')方法加工为一个个数组 并赋值给返回值中
    • 使用标签页点击事件 当点击商品属性标签页时 发送ajax请求 获取商品静态属性 在表单中 通过for循环商品静态属性 渲染 label属性值和输入框双向绑定数据值
  8. 图片上传和预览

    • 引入上传组件 属性绑定headers 配置请求头
    • on-success 上传成功回调中 将当前图片的路径push到添加商品数据模板中
    • on-remove 根据当前图片的临时路径 查询在数据模板中的索引并删除
    • 创建一个对话框 对话框里包含一个图片 为图片绑定一个路径数据模板
    • on-preview 点击预览图片时 获取当前图片的项目路径 保存 在数据模板 开启对话框
  9. 富文本编辑器依赖

    • npm install vue-quill-editor
    • 在main.js中 引入 vue-quill-editor及依赖 并开放到全局组件
    • 组件中通过标签使用 并未其双向数据绑定到添加商品数据模板中
  10. 添加商品

  • 点击按钮触发添加商品函数
  • 函数中使用表单引用对象预验证表单
  • 有的请求数据需要转换为字符串 但是由于是双向数据绑定 所以需要深拷贝一份添加商品数据模板 这里可以使用 lodash 依赖
    • npm i lodash
    • import _ from ‘lodash’ 引入
    • _.cloneDeep(克隆对象)
  • 循环动态参数和静态参数 数据模板 的 id和 val值 按照接口文档 封装为一个对象 并添加到添加商品数据模板的attrs数组中
  • 根据克隆的数据模板发送请求添加商品 成功添加则跳转到商品列表页面
  1. 提交代码到码云中
Vue订单列表功能
  1. 创建order订单分支并搭建页面基本结构
    • 使用git命令创建并切换到order分支 并同步到码云
    • 创建order.vue添加路由 并搭建基本结构 面包屑和卡片组件
  2. 渲染订单列表
    • 页面搭建完毕时发送请求获取订单列表数据
    • 创建表格组件 并根据订单列表数据渲染表格
  3. 渲染分页
    • 根据订单数据列表中的数据创建并渲染分页组件
  4. 修改地址
    • 为按钮添加点击事件 弹出对话框 并放入表单组件
    • 使用import 引入 省市区三级联动js文件 并在data 中保存其数据
    • 使用级联选择器 双向数据绑定引入的数据
  5. 物流进度
    • 创建物流进度对话框
    • 点击按钮展示对话框 并发送请求获取物流进度数据
    • 在element中 通过import 引入时间线组件 的js文件 并开放到全局中
    • 对话框中创建时间线组件 并通过请求获取的数据渲染组件
    • style 中 使用@import 引入时间线组件的css文件
  6. 将代码同步到码云
数据统计
  1. 创建report订单分支并搭建页面基本结构
    • 使用git命令创建并切换到report分支 并同步到码云
    • 创建report.vue添加路由 并搭建基本结构 面包屑和卡片组件
  2. 渲染数据列表
    • npm i echarts 下载渲染图标的依赖
    • import 引入图标依赖 和lodash合并对象依赖
    • mounted 回调中 发送请求获取数据获取数据列表数据
    • 将返回的数据 和接口中需要合并的数据对象 使用 lodash依赖的merge方法 合并为一个对象
    • 按照图表教程将合并的数据显示即可
优化
  1. nprogress优化进度条效果
    • npm install nprogress
    • 通过import 引入nprogress 及其样式
    • 在axios 请求拦截器中 调用 引入对象的start()方法
    • 在axios 响应拦截器中 调用 引入对象的 done()方法
  2. 移除所有console.log
    • npm install babel-plugin-transform-remove-console -D 在开发依赖中安装
    • 根据process.env.NODE_ENV === ‘production’ 判断为发布模式时
    • babel.config.js中plugins数组中添加 ‘transform-remove-console’ 就可以移除所有的console
    • 需要重新运行项目才可生效
$
  • this.$nextTick() 当页面渲染之后调用其中的回调 可用于获取表单焦点

小技巧

  • 如果页面获取的数据是数据库全部的数据 就不用再发送请求查询数据了,直接对获取的数据进行查询即可
  • vs-code插件 : prettier - code formatter 格式化插件

你可能感兴趣的:(Vue,webpack,vuex)