【前端篇】html、css、JavaScript、vue基础知识

基础

  • 静态资源:
    • HTML:用于搭建基础网页,展示页面的内容
    • CSS:用于美化页面,布局页面
    • JavaScript:控制页面的元素,让页面有一些动态的效果

Html5

详细参见:思维脑图

基础标签

1、标题标签: h1  到  h6
2、段落标签:p
3、字体加粗:b    字体倾斜:em
4、换行:br(非成对出现的)
5、分割线: hr
6、表示一块内容:div  (没有特殊的效果)
    在html5中支持自定义标签,自定义的标签和div标签的用法是一样的
7、行内块元素:span
8、图像标签:img
        src属性:指定图片地址
        alt: 指定图片未加载出来时的提示
9、超连接标签:a
10、音频播放器:audio
11、视频播放器:video
12、无序列表:ul
13、有序列表:ol
14、表格:table

表单标签

表单:form
    input:输入框
    type属性:
            text:文本
            password:密码
            submit:提交按钮(点击之会主动提交表单)
            button:普通按钮(点击之后没有特殊效果)
            checkbox:多选框
            radio:单选框
            file:文件上传
            hidden:影藏的表单域(预设一个要传递的参数和值,但是不会在页面上显示)
            reset:情况表单内容

    name:表单的参数名
    value:表单的值
    placeholder:表单的提示内容

label标签:将表单前的提示内容和表单进行关联;当点击label标签内容时,会自动将焦点聚焦于关联的表单上

textarea标签:文本输入框

CSS3

基本使用

1、通过link标签引入外部的css文件
<link rel="stylesheet" href="css/a.css">

2、在head中通过style标签定义样式
<style>
    div{
        color:blue;
    }
</style>

3、在标签中通过style属性定义样式
如:<div style="color:red;">hello css</div>

选择器

1. 基础选择器
	1. id选择器:选择具体的id属性值的元素.建议在一个html页面中id值唯一
        * 语法:#id属性值{}
    2. 元素选择器:选择具有相同标签名称的元素
        * 语法: 标签名称{}
        * 注意:id选择器优先级高于元素选择器
    3. 类选择器:选择具有相同的class属性值的元素。
        * 语法:.class属性值{}
        * 注意:类选择器选择器优先级高于元素选择器
2. 扩展选择器:
	1. 选择所有元素:
		* 语法: *{}
	2. 并集选择器:
		* 选择器1,选择器2{}
	
	3. 子选择器:筛选选择器1元素下的选择器2元素
		* 语法:  选择器1 选择器2{}
	4. 父选择器:筛选选择器2的父元素选择器1
		* 语法:  选择器1 > 选择器2{}

	5. 属性选择器:选择元素名称,属性名=属性值的元素
		* 语法:  元素名称[属性名="属性值"]{}

	6. 伪类选择器:选择一些元素具有的状态
		* 语法: 元素:状态{}
		* 如: <a>
			* 状态:
				* link:初始化的状态
				* visited:被访问过的状态
				* active:正在访问状态
				* hover:鼠标悬浮状态

背景

/* 设置背景颜色 */
/*background: yellow;*/

/* 设置图片作为背景 */
background-image: url('./images/bj.png');

/* 设置背景是否平铺
background-repeat: 
no-repeat; 不进行平铺
repeat-y; y轴平铺
repeat-x; x轴平铺 */
background-repeat: no-repeat;

/* 设置背景的定位 */
background-position:50px 100px;

/* 固定背景位置 */
background-attachment:fixed;

/* 设置背景大小 */
background-size:200px 100px ;			

文本样式

color: #FF0000; 字体颜色
font-size: 36px;  大小
font-weight: bold; 是否加粗
font-style: italic;  是否倾斜
font-family: '微软雅黑';  字体样式
line-height  行高
font: 字体是否加粗   字体大小/行高  字体样式
text-indent: 36px;  设置文字首行缩进

text-align:设置文件对齐位置

盒子模型(控制布局)

* margin:外边距
* padding:内边距
	* 默认情况下内边距会影响整个盒子的大小
	* box-sizing: border-box;  设置盒子的属性,让width和height就是最终盒子的大小

为什么要进行浮动:页面横向布局
* float:浮动
	* left
	* right
浮动塌陷的问题:父级元素在没有设置高度的情况下,子元素浮动会造成浮动塌陷(父元素后面的元素会显示到浮动的元素下面)
解决方案1、:给父元素设置:overflow: hidden;

定位

相对定位 relative:相对于原来在文档流的位置进行偏移
绝对定位 absolute: 根据已经进行定位的父级元素进行偏移
(通常在使用绝对定位时,会将父级元素设置为相对定位,简称子绝父相)
固定位置定位 fixed

显示(display)

display属性:可以控制元素的显示和隐藏
display: none隐藏元素
display:block(默认,元素可见)

display:block/inline-block 主要用于行内标签(如a span还有特殊img)宽高设置不生效


JavaScript(JS)

基本语法

引入

1、第一种:行间事件: 直接在元素上 通过给元素添加事件绑定,来执行js代码
<button type="button" onclick="alert(123456)">按钮1</button>

2、第二种:通过script标签引入外部的js文件
<script type="text/javascript" src="js/main.js"></script>

3、第三种:直接页面的script标签中编写js代码
<script>
	function musen(){
		alert('musen123')
	}
</script>

注释

1. 单行注释://注释内容
2. 多行注释:/*注释内容*/

变量

var:定义的变量可以跨代码块访问(全局变量)。

	
let:定义块级作用局的变量(代码块内的局部变量)
const: 定义常量,初始化必须赋值,值不可修改,只能在块级作用域访问
	{} :包起来的代码,就是代码块

数据类型

1. 原始数据类型(基本数据类型)1. number:数字。 整数/小数/NaN(not a number 一个不是数字的数字类型)
	2. string:字符串。 字符串  "abc" "a" 'abc'
	3. boolean: true和false
	4. null:一个对象为空的占位符
	5. undefined:未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined
	
2. 引用数据类型:对象

对象

对象的定义:1、{}   ,2、new Object()

对象的属性和方法:
	属性名:属性值
	方法名:函数

对象中的this:代表的是对象本身
var objA = {
			name:'木森',
			age:18,
			func1:function(){
				console.log('objA的func1方法')
			},
			func2:function(){
				console.log('打印对象中的this')
				console.log(this.name)
			}
		}

函数

function 方法名称(形式参数列表){
        方法体
    }
		1、函数的定义:
		function printUserInfo(name,age){
			console.log('我的名字:'+name+'我的年纪:'+age)
		}
		
		2、函数的返回值
		function addNumber(a,b){
			// 返回a+b的结果
			return a+b
		}
		//  扩展:函数中的this:代表的是window对象(窗口)
		function work01(){
			console.log(this)
		}



var 方法名 = function(形式参数列表){
     方法体
}
// es6中箭头函数
// 箭头函数和普通函数中this的区别
// 普通函数里的this代表的所在作用域的对象,即对象中普通函数里的this指对象本身
// 箭头函数里的this代表的所在作用域的外层作用域的对象,即对象中箭头函数里的this指当前对象外层作用域的对象
var objA ={
	// 箭头函数
	func: ()=>{
		console.log('这个是func方法')
	},
	func3:(a,b)=>{
		return a+b
	},
	// 箭头函数只有一个参数时,括号可以省略
	func4:a=>{
		console.log(a)
		// 这个this代表的window对象
		console.log(this)
	},
	func2:function (){
		console.log('这个是func2方法')
		// this代表objA
		console.log(this)
	}
}

流程控制语句

1、if-else语句
if(10>20){
	console.log('10>5成立!')
}else{
	console.log('10>5不成立!')
}

2、if- else if -else
var number = 55
if (number>=80){
	console.log('成绩很优秀')
}else if( number>=60){
	console.log(number)
	console.log('成绩及格')
}else{
	console.log('成绩不及格')
}

3、while循环
// break 和continue关键字和python中的作用时一样的
var count = 1
while(count<=10){
	console.log(count)
	count++
	// 当count等于5时,强制退出循环
	if (count==8){
		// break
		// continue
	}
	console.log(`--------------`)
}

4、for循环
(1)for条件循环 :for(循环开始之前执行的代码,是否执行循环体的条件,循环体执行完执行执行的代码)
 for (var i=1;i<=10;i++){
	 console.log(i) 
 }
 
(2)for 遍历循环
// 注意点:for循环遍历数组时,遍历出来的时数组的索引
var arryA = [11,22,33,44]
for循环遍历数组
for(i in arryA){
	console.log(i,arryA[i])
}

// 注意点:for循环遍历对象时,遍历出来的是对象的属性名
var objA = {
	name:'木森',
	age:18,
	func1:function(){
		console.log('objA的func1方法')
	},
	func2:function(){
		console.log('打印对象中的this')
		console.log(this.name)
	}
}
// for循环遍历对象
for (i in objA){
	console.log(i,objA[i])
}

数组遍历、过滤和查找

// forEach遍历数组
arryA.forEach(function (item,i,arry){
	// item 是遍历出来的值
	// i 是对应的索引
	//arry 是数组本身
	console.log(item,i,arry)
})

// filter:遍历数组,进行过滤
var res = arryA.filter(function(item,i){
	return item>50
})
console.log(res)

// find方法:查找第一个符合条件的值
var res = arryA.find(function(item,i){
	return item ==33
})
console.log(res)

JS操作页面

// window.onloan 是窗口的一个事件,这个事件会等到页面元素加载完毕之后才会执行
window.onload = function(){
	document.querySelector('#box1').innerText='python001'
}


VUE2

浏览器安装vue devtools可用于调试vue程序

基础语法

基本使用

  • 引入vue
  • 声明控制的DOM区域
  • 创建vue实例
    • el:指向视图view
    • data:指向数据model
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- 引入vue -->
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<div>{{name}}</div>
			<div>{{age}}</div>
			<div>{{gender}}</div>
			<button type="button" @click="add()">+</button>
			<button type="button" @click="sub()">-</button>
		</div>
		

		<script type="text/javascript">
			/*
			{{}}:插值表达式
	
			*/ 
			var vue = new Vue({
				// el 是vue绑定的页面元素
				el: "#app",
				// data:  是绑定到页面中的数据
				data:{
					name:'musen',
					age:18,
					gender:'男'
				},
				methods:{
					// vue方法中的this代表的vue这个对象
					add:function(){
						this.age++
					},
					sub:function(){
						this.age--
					}
				},
				
				
			})
		</script>


	</body>
</html>

vue指令

v-text、v-html(文本插值)
<标签名 v-text="vue中data的key"></标签名> 
<标签名 v-html="vue中data的key"></标签名>
说明:文本插值v-html通过data的key获取value显示标签的文本中

插值表达式{{}}不解析html标签,不能使用在属性中

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>

		<div id="box">
			<span>{{user}}</span>
			<span v-text="user"></span>
			<div v-html="info"></div>
			<div v-pre>{{info}}</div>
		</div>

		<script type="text/javascript">
			/*
			常见指令: 
			v-text:往标签中插入文本值
			v-html:往标签中插入html元素
			v-pre:在标签中显示原始文本内容
			*/
			var vue = new Vue({
				el: '#box',
				data: {
					user: '小柠檬',
					info: '<h1>python</h1>',
					status:false
				}
			})
		</script>

	</body>
</html>

v-bind(属性绑定)

单向数据绑定,脚本改变,视图改变

<标签名 v-bind:属性名="data中key"></标签名>
简写:常用
<标签名 :属性名="data中key"></标签名>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

		<style type="text/css">
			.hide {
				width: 100px;
				height: 200px;
				background: red;
			}

			.hide2 {
				width: 100px;
				height: 200px;
				background: blue;
			}
		</style>


	</head>
	<body>
		<div id="box">
			<!-- <div class="hide">1</div> -->
			<!-- <hr> -->
			<!-- 	<div v-bind:class="cls">2</div>
			<hr>
			<div v-bind:class="[cls]">3</div>
			<hr>
			<div :class="{hide:status}">4 </div>
			 -->
			 <a :href='addr'>淘宝</a>
			 <a :href="addr2" :musen='musen' >百度</a>
		</div>



		<script type="text/javascript">
			/**
			 * v-bind  可以简写为 :
			 * v-bind:属性值 = 绑定的数据
			 */
			var vue = new Vue({
				el: '#box',
				data: {
					cls: 'hide',
					status: true,
					addr:'http://www.taobao.com',
					addr2:'http://www.baidu.com',
					musen:'1234'
				}
			})
		</script>
	</body>
</html>

v-model(双向绑定)

仅用于input、select、textarea标签
双向数据绑定,脚本改变,视图改变,视图改变,脚本也改变

<标签名 v-model="vue中data的key"></标签名>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<input type="text" v-model="info">
			<div>{{info}}</div>
		</div>

		<script type="text/javascript">
			var vue = new Vue({
				el:'#app',
				data:{
					info: 'python'
				}
			})
		</script>
	</body>
</html>

v-on(事件绑定)
<标签名 v-on:事件名="执行函数"></标签名> 
简写:重点记忆
<标签名 @事件名="执行函数"></标签名> 
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<table border="" cellspacing="" cellpadding="">
				<tr>
					<th>ID</th>
					<th>接口名</th>
					<th>测试人员</th>
					<th>项目名</th>
					<th>项目ID</th>
					<th>描述信息</th>
					<th>创建时间</th>
					<th>用例数</th>
					<th>操作</th>
				</tr>
				<tr :key='item.id' v-for="item in lists">
					<td>{{item.id}}</td>
					<td>{{item.name}}</td>
					<td>{{item.tester}}</td>
					<td>{{item.project}}</td>
					<td>{{item.project_id}}</td>
					<td>{{item.desc}}</td>
					<td>{{item.create_time}}</td>
					<td>{{item.testcases}}</td>
					<td><button @click="del(item.id)">删除</button></td>
				</tr>
			</table>
			<hr>
		
		</div>
		<script type="text/javascript">
			/*
			给绑定的事件传递参数
			*/ 
			var vue = new Vue({
				el: '#app',
				data: {
					lists: [{
							"id": 1,
							"name": "登录接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "登录接口",
							"create_time": "2019-11-06 14:50:30",
							"testcases": 9,
						},
						{
							"id": 2,
							"name": "注册接口_自动化测试平台项目",
							"tester": "可可",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "自动化测试平台项目, 注册接口",
							"create_time": "2019-11-06 14:51:00",
							"testcases": 0,
						},
						{
							"id": 3,
							"name": "创建项目接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "这是自动化测试平台创建项目接口",
							"create_time": "2019-11-06 14:51:45",
							"testcases": 1,
						},
						{
							"id": 4,
							"name": "注册接口_前程贷P2P金融项目",
							"tester": "小可可",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 14:52:22",
							"testcases": 0,
						},
						{
							"id": 5,
							"name": "登录接口_前程贷P2P金融项目",
							"tester": "柠檬小姐姐",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 14:52:40",
							"testcases": 0,
						},
						{
							"id": 6,
							"name": "查看项目列表接口_前程贷P2P金融项目",
							"tester": "柠檬小姐姐",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 17:22:50",
							"testcases": 1,
						}
					],
					
				},
				methods:{
					del:function(id){
						// 删除数据的方法
						console.log('删除一行数据',id)
						// 从lists中删除对应的数据
						// 通过过滤的方式删除数组中的数据
						// this.lists= this.lists.filter(function(item,index){
						// 	return item.id !=id
						// })
						
						// 查找要删除的数据索引值
						let index = this.lists.findIndex(function(item){
							return item.id==id
						})
						// 根据数组的索引去删除数组中对应的数据
						this.lists.splice(index,1)
						
					}
					
				}
			})
		</script>


	</body>
</html>

v-if、v-show(条件渲染)
// v-if  如果满足某个条件,那么就显示文本,不满足就无
<标签名 v-if="判断条件">文本</标签名>
<标签名 v-else-if="判断条件">文本</标签名>
....
<标签名 v-else>文本</标签名>


// v-show  如果满足某个条件,那么就显示文本,不满足就隐藏 display:none 
<标签名 v-show="判断条件">文本</标签名>

v-if 示例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		
	</head>
	<body>
		<div id="app">
				<div>
				<span v-text="user"></span>
				<span v-text="score"></span>
				<span v-if="score>80">优秀</span>
				<span v-else-if="score>60">良好</span>
				<span v-else=>不及格</span>
				</div>
			
		</div>
		<script type="text/javascript">
			/*
			0-60   不及格
			60--80  良好
			80-100  优秀
			vue中的条件判断语句:根据不同的条件显示不同的内容
			v-if
			v-else-if
			v-else:
			
			*/	
			var vue = new Vue({
				el:"#app",
				data:{
					stus:[
						{name:'木森',score:100},
						{name:'盼盼达',score:78},
						{name:'好好先生',score:89},
						{name:'枫',score:99},
					],
					score:88,
					user:'musen'
				}
				
			})
			
		</script>
		
	</body>
</html>

v-show 示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>条件渲染</title>
</head>
<body>
<div id="div">
    
    <!--v-show指令-->
    <div v-show="flag">div4</div>

    <!--
       v-if  v-show 他们俩虽然都是控制元素是否显示,但是底层的原理不一样
           v-if 如果条件为false,页面中根本没有这个元素
           v-show如果条件为false,页面中有这个元素只不过它的display属性值为none
   -->
</div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: "#div",
        data: {
            num: 2,
            flag: false
        }
    });
</script>
</html>

v-for(循环)
<标签名 v-for="变量名 in 容器或者对象名">{{变量名}}</标签名> 
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<table border="" cellspacing="" cellpadding="">
				<tr>
					<th>姓名</th>
					<th>成绩</th>
					<th>等级</th>
				</tr>
				<!-- // key 需要指定一个数据中唯一的值 -->
				<tr v-for='item in stus' :key='item.score'>
					<td>{{item.name}}</td>
					<td>{{item.score}}</td>
					<td v-if="item.score>80">优秀</td>
					<td v-else-if="item.score>60">良好</td>
					<td v-else>不及格</td>
				</tr>
			</table>

		</div>
		<script type="text/javascript">
			/*
			0-60   不及格
			60--80  良好
			80-100  优秀			
			v-for:循环语句
			
			*/
			var vue = new Vue({
				el: "#app",
				data: {
					stus: [{
							name: '木森',
							score: 100
						},
						{
							name: '盼盼达',
							score: 78
						},
						{
							name: '好好先生',
							score: 89
						},
						{
							name: '枫',
							score: 99
						},
					],
					score: 88,
					user: 'musen'
				}

			})
		</script>





	</body>
</html>

高级特征

修饰符

事件修饰符
 <!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<div @click="work3">
				<div @click="work2()">
					<button type="button" @click.stop="work1()">按钮1</button>
					<a href="http://www.baidu.com" @click.prevent.stop="handleA()">百度</a>
				</div>
			</div>

		</div>

		<script type="text/javascript">
			/*
			事件冒泡:子元素触发某个事件之后,会依次将这个事件传递给父元素
			vue事件修饰符:
				stop: 阻止事件冒泡
				prevent:阻止元素默认的事件行为
			*/


			var vm = new Vue({
				el: '#app',
				data: {},
				methods: {
					work1: function() {
						console.log('work1-----')
					},
					work2: function() {
						console.log('work2-----')
					},
					work3: function() {
						console.log('---work30000')
					},
					handleA:function(){
						console.log('点击了a标签')
					}
				}
			})
		</script>


	</body>
</html>

按键修饰符
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<form action="">
				账号:<input type="text" v-model.lazy="loginForm.user"> <br>
				密码:<input type="password" v-model="loginForm.pwd" @keyup.enter="login_btn()"><br>
				<button type="button" @click="login_btn()">点击登录</button>
			</form>

		</div>

		<script type="text/javascript">
			/*
			事件冒泡:子元素触发某个事件之后,会依次将这个事件传递给父元素
			vue事件修饰符:
				stop: 阻止事件冒泡
				prevent:阻止元素默认的事件行为
				
			按键修饰符
				keyup.enter:回车键
			
			表单修饰符:
				trim:去除输入首尾的空白
			
			
			
			*/

			Vue.config.keyCodes.a = 65
			var vm = new Vue({
				el: '#app',
				data: {
					loginForm:{
						user:'',
						pwd:''
					}
				},
				methods: {
					login_btn:function(){
						alert('点击了登录')
					}
				}
			})
		</script>


	</body>
</html>

表单修饰符
/// 在 "change" 事件后同步更新而不是 "input",比如回车或者失去焦点
<input v-model.lazy="msg" />

// 输入自动转换为数字
<input v-model.number="age" />

// 默认自动去除用户输入内容中两端的空格
<input v-model.trim="msg" />

计算属性(computed)

计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<h3>产品名:{{name}}</h3>
			<h3>单价:{{price}}</h3>
			<h3>
				数量:
				<button type="button" @click="sub()">-</button>
				<span>{{num}}</span>
				<button type="button" v-on:click="add()">+</button>
			</h3>
			<hr>
			<!-- <h2>合计金额:{{sum_func()}}</h2> -->
			<h2>合计金额:{{sum}}</h2>
		</div>
		<script type="text/javascript">
			/**
			 *计算属性:通过computed进行定义
			  作用:
			 * 
			 * 
			 */ 
			var vue = new Vue({
				el: '#app',
				data: {
					name: '小柠檬',
					price: 8,
					num: 0,
				},
				methods: {
					add: function() {
						this.num++
					},
					// 定义方法时:将function省略,和上面定义的add方法没有区别
					sub() {
						this.num--
					},
					// sum_func(){
					// 	return this.price * this.num
					// }
				},
				// 定义计算属性,
				computed: {
					sum: function() {
						return this.price * this.num
					}
				},

			})
		</script>



	</body>
</html>

侦听器(watch)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="box">
			数量:
			<button type="button" @click="sub()">-</button>
			<input type="text" :value="number">
			<button type="button" v-on:click="add()">+</button>
			<hr>
			<input type="text" v-model.lazy="name">
				
		</div>

		<script type="text/javascript">
			/**
			 *  侦听器 监测数据的值是否发生变化
			 */
			var vue = new Vue({
				el: '#box',
				data: {
					number:0,
					name :'musen'
				},
				methods:{
					add:function(){
						this.number++
					},
					// 定义方法时:将function省略,和上面定义的add方法没有区别
					sub(){
						this.number--
					}
					
				},

				// 侦听器 
				watch:{
					number:function(value){
						console.log('监测到number的值发生了变化',value)
						if (value<0){
							alert('数量不能少于0')
							this.number=0
						}	
					},
					name:function(value){
						console.log('监测到name的值发生了变化',value)	
					}
				}
			})
			
			
		</script>;
	</body>
</html>

过滤器(filters)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<h3>产品名:{{name}}</h3>
			<h3>单价:{{price | dubboFloat}}</h3>
			<h3>
				数量:
				<button type="button" @click="sub()">-</button>
				<span>{{num}}</span>
				<button type="button" v-on:click="add()">+</button>
			</h3>
			<hr>
			<!-- <h2>合计金额:{{sum_func()}}</h2> -->
			<h2>合计金额:{{sum | dubboFloat}}</h2>
			<h2>{{info| upper}}</h2>
		</div>
		<script type="text/javascript">
		
			var vue = new Vue({
				el: '#app',
				data: {
					name: '小柠檬',
					price: 8,
					num: 0,
					info:'python'
				},
				methods: {
					add: function() {
						this.num++
					},
					// 定义方法时:将function省略,和上面定义的add方法没有区别
					sub() {
						this.num--
					}
				
				},
				// 定义计算属性,
				computed: {
					sum: function() {
						return this.price * this.num
					}
				},
				// 定义过滤器
				/*
				主要用来对页面显示的数据,做一些格式化的处理
				*/
				filters:{
					dubboFloat:function(value){
						
						// 格式化数值,显示两位小数
						return value.toFixed(2)
					},
					upper:function(value){
						// 将字符串中的小写字符转换为答谢
						return value.toUpperCase()
					}
					
				}

			})
		</script>



	</body>
</html>

vue生命周期

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<div>{{message}}</div>
			<button @click="update01">按钮</button>
			<button type="button" @click="btn">销毁</button>
		</div>


		<script>
			var vm = new Vue({
				el: '#app',
				data: {
					message: '木森'
				},
				methods:{
					update01:function(){
						this.message='mmmmm'
					},
					btn:function(){
						//销毁vue实例对象
						this.$destroy()
					}
				},
				
				beforeCreate: function() {
				    console.group('------beforeCreate--vue创建前状态------');
				    console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
				    console.log("%c%s", "color:red", "data   : " + this.$data); //undefined 
				    console.log("%c%s", "color:red", "message: " + this.message)
							},
				created: function() {
				    console.group('------created--vue创建完毕状态------');
				    console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
				    console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化 
				    console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
							},
				beforeMount: function() {
				    console.group('------beforeMount,data数据挂载前状态------');
				    console.log("%c%s", "color:red", "el     : " + (this.$el)); //已被初始化
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化  
				    console.log("%c%s", "color:red", "message: " + this.message); //已被初始化  
							},
				mounted: function() {
				    console.group('------mounted data数据挂载结束状态------');
				    console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
				    console.log("%c%s", "color:red", "message: " + this.message); //已被初始化 
							},
				beforeUpdate: function() {
				    console.group('beforeUpdate  data数据更新前状态==============');
				    console.log("%c%s", "color:red", "el     : " + this.$el);
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : " + this.$data);
				    console.log("%c%s", "color:red", "message: " + this.message);
							},
				updated: function() {
				    console.group('updated  data数据更新完成状态==============');
				    console.log("%c%s", "color:red", "el     : " + this.$el);
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : " + this.$data);
				    console.log("%c%s", "color:red", "message: " + this.message);
							},
				beforeDestroy: function() {
				    console.group('beforeDestroy  vue对象销毁前状态==============');
				    console.log("%c%s", "color:red", "el     : " + this.$el);
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : "+ this.$data);
				    console.log("%c%s", "color:red", "message: " + this.message);
							},
				destroyed: function() {
				    console.group('destroyed  vue对象销毁完成状态==============');
				    console.log("%c%s", "color:red", "el     : " + this.$el);
				    console.log(this.$el.innerHTML);
				    console.log("%c%s", "color:red", "data   : "+ this.$data);
				    console.log("%c%s", "color:red", "message: " + this.message)
				                }
			})
		</script>





	</body>
</html>


组件化开发

组件注册和使用

全局注册
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<style>
			.title {
				background: #0000FF;
				height: 80px;
				margin-bottom: 5px;
			}

			.content {
				background: #FAEBD7;
				height: 1000px;
			}

			.footer {
				margin-top: 10px;
				background: #9ACD32;
				height: 100px;
			}

			.left {
				width: 15%;
				background: #00FFFF;
				height: 100%;
				float: left;
				margin-right: 0.5%;
			}

			.right {
				width: 84%;
				background: #FF0000;
				height: 100%;
				float: left;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<!-- 顶部菜单栏 -->
			<div class="title">
				<header-con></header-con>
				<!-- <HeaderCon></HeaderCon> -->
			</div>
			<!-- 中间的主题内容 -->
			<div class="content">
				<!-- 左边的菜单 -->
				<div class="left">
					<left-con></left-con>
				</div>
				<!-- 右边的内容 -->
				<div class="right">
					<right-con></right-con>
					
				</div>
			</div>
		</div>

	

		<script type="text/javascript">
			/*
			1、定义组件:
				全局组件:使用Vue.component定义组件
			2、在页面中使用组件 <组件名></组件名>
			
			3、组件名的命名注意点:
				如果定义组件的时候,组件名使用的是大驼峰的命名风格,在页面中引用组件的时候 ,
				要使用中划线命名风格(xx-xx)
				
			4、定义的全局组件 可以再其他的组件中直接引用
				注意点:在组件的版本中引用其他组件可以使用大驼峰命名法
			
			建议:组件命名尽量使用中划线命名风格  xxx-xxx
			*/ 
			
			
			//  全局的组件定义:
			// Vue.component('header-con', {
			// 	template: `
			// 	<div><h1>这个是页面头部组件</h1></div>
			// 	`
			// })
			Vue.component('HeaderCon', {
				template: `
				<div><h1>这个是页面头部组件9999</h1></div>
				`
			})
			
			Vue.component('left-con', {
				template: `
				<div> <h1>这个是页面左边内容的组件</h1>
				<my-button></my-button></div>
				`

			})
			Vue.component('right-con', {
				template: `
				<div> 
				<h1>这个是页面左边内容的组件</h1>
				<my-button></my-button>
				<MusenButton></MusenButton>
				</div>
				`

			})
			
			Vue.component('my-button',{
				template:`
				<button>mybutton</button>
				`
			})
			Vue.component('MusenButton',{
				template:`
				<button>musen</button>
				`
			})

			var vm = new Vue({
				el: '#app',
				data: {

				},

			})
		</script>


	</body>
</html>

局部注册
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<header-con></header-con>
			<left-con></left-con>
		</div>
		<script type="text/javascript">
			/*
			
			*/
			var vm = new Vue({
				el: '#app',
				data: {

				},
				// 定义局部组件:只能在父组件(页面)中使用,不能在其他的组件中引用
				components: {
					// 组件名要使用引号包起来,不然会报语法错误-
					'header-con': {
						template: `
						<button>按钮1</button>
						`
					},
					'left-con': {
						template: `
						<div>
							<span>python666</span>
						</div>
						`
					}
				}
			})
			
		</script>


	</body>
</html>

组件名格式
 <!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<header-con></header-con>
			<left-con></left-con>
		</div>
		<script type="text/javascript">
			/*
			1、组件中的数据 同样放在data字段中,
				注意点:组件中的data是一个方法(函数),数据为函数return返回出来的内容
				注意点:组件的模板内容,必须有一个根节点(最外层只有一个标签)
			2、组件中的方法:定义在methods中
			
			
			*/
			var vm = new Vue({
				el: '#app',
				data: {
					name: '木森',
					age: 99
				},
				// 定义局部组件:只能在父组件(页面)中使用,不能在其他的组件中引用
				components: {
					// 组件名要使用引号包起来,不然会报语法错误-
					'header-con': {
						template: `
						<button @click='handleClick'>按钮1</button>
						`,
						methods: {
							handleClick: function() {
								console.log('----handleClick-----')
							}
						},
					},
					'left-con': {
						template: `
						<div>
							<h2>名字{{name}}</h2>
							<h2>名字{{age}}</h2>
							<h2>计算属性sum:{{sum}}</h2>
							<span>python666</span>
						</div>
						`,
						// 组件中的数据 同样放在data字段中,
						// 注意点:组件中的data是一个方法(函数),数据为函数return返回出来的内容
						data: function() {
							return {
								name: 'musen',
								age: 18
							}
						},
						computed: {
							sum: function() {
								return this.name + this.age
							}
						},
						watch: {
							age: function(val) {
								console.log(val)
							}
						}
					}
				}
			})
		</script>


	</body>
</html>

父组件往子组件中传数据

父组件在引用子组件时,通过属性绑定的形式(即:自子组件自定义的属性名)传递参数
子组件中通过props定义接收数据的参数名(子组件的属性名)

注意:子组件传值注意-加冒号和不加冒号区别

  • 父组件向子组件传值,如果不加:冒号,传过去的不是数值,而是一个字符串
  • 父组件向子组件传值,加上:冒号,传过去的就是一个数值,不是字符串,因为加了:冒号以后引号""里面的内容就是一个js表达式
  • 只有传递字符串常量时,不采用v-bind形式,其余情况均采用v-bind形式传递。
  • 如果不加冒号,子组件在接收到值之后,监听做不到改变监听值内的属性
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	</head>
	<body>
		<div id="app">
			<data-views :lists="cases1"></data-views>
			<data-views :lists="cases2"></data-views>
		</div>


		<script type="text/javascript">
			/*
			场景:父组件中引用子组件的时候,给子组件传递数据
			实现步骤:
				1、在子组件中通过props来定义接收数据的参数名(子组件的属性名)
				2、父组件在引用子组件时,通过属性绑定的形式传递参数
			*/ 
			
			Vue.component('data-views', {
				// 指定父组件中引用该组件时,传递数据的参数名
				props:['lists'],
				template: `
				<table border="" cellspacing="" cellpadding="">
					<tr>
						<th>ID</th>
						<th>接口名</th>
						<th>测试人员</th>
						<th>项目名</th>
						<th>项目ID</th>
						<th>描述信息</th>
						<th>创建时间</th>
						<th>用例数</th>
					</tr>
					<tr :key='item.id' v-for="item in lists">
						<td>{{item.id}}</td>
						<td>{{item.name}}</td>
						<td>{{item.tester}}</td>
						<td>{{item.project}}</td>
						<td>{{item.project_id}}</td>
						<td>{{item.desc}}</td>
						<td>{{item.create_time}}</td>
						<td>{{item.testcases}}</td>
					</tr>
				</table>
				`
			})

			var vm = new Vue({
				el: '#app',
				data: {
					cases1:[{
							"id": 1,
							"name": "登录接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "登录接口",
							"create_time": "2019-11-06 14:50:30",
							"testcases": 9,
						},
						{
							"id": 2,
							"name": "注册接口_自动化测试平台项目",
							"tester": "可可",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "自动化测试平台项目, 注册接口",
							"create_time": "2019-11-06 14:51:00",
							"testcases": 0,
						}],
					cases2:[
						{
							"id": 3,
							"name": "创建项目接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "这是自动化测试平台创建项目接口",
							"create_time": "2019-11-06 14:51:45",
							"testcases": 1,
						},
						{
							"id": 4,
							"name": "注册接口_前程贷P2P金融项目",
							"tester": "小可可",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 14:52:22",
							"testcases": 0,
						},
						{
							"id": 5,
							"name": "登录接口_前程贷P2P金融项目",
							"tester": "柠檬小姐姐",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 14:52:40",
							"testcases": 0,
						},
						{
							"id": 6,
							"name": "查看项目列表接口_前程贷P2P金融项目",
							"tester": "柠檬小姐姐",
							"project": "前程贷P2P金融项目",
							"project_id": 2,
							"desc": "",
							"create_time": "2019-11-06 17:22:50",
							"testcases": 1,
						}
					]
				}


			})
		</script>



	</body>
</html>

子组件往父组件中传数据

  • 在子组件中通过$emit来触发一个自定义的事件,并把数据传递过去

    $emit('自定义的事件名',传递的数据)
    
  • 父组件在引用子组件时,通过事件监听机制,来监听子组件自定义的事件,并指定方法去处理这个事件

    @自定义的事件名 = 处理事件的方法($event)
    
  • 在处理事件的方法中接收数据,并处理

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<data-views :lists="cases1" @run='recvData($event)'></data-views>
			<hr>
			<div>
				<h3>执行的用例信息:{{info}}</h3>
			</div>
		</div>
		
		<script type="text/javascript">
			/*
			场景:一般子组件在操作某个数据之后,要将数据传递给父组件,就要用到子组件给父组件传递数据,
			实现步骤:
				1、在子组件中通过$emit来触发一个自定义的事件,并把数据传递过去
					$emit('自定义的事件名',传递的数据)
				2、父组件在引用子组件时,通过事件监听机制,来监听子组件自定义的事件,并指定方法去处理这个事件
					@自定义的事件名 = 处理事件的方法($event)
				3、在处理事件的方法中接收数据,并处理
			*/ 
			
			Vue.component('data-views', {
				// 指定父组件中引用该组件时,传递数据的参数名
				props:['lists'],
				template: `
				<table border="" cellspacing="" cellpadding="">
					<tr>
						<th>ID</th>
						<th>接口名</th>
						<th>测试人员</th>
						<th>项目名</th>
						<th>项目ID</th>
						<th>描述信息</th>
						<th>创建时间</th>
						<th>用例数</th>
						<th>操作</th>
					</tr>
					<tr :key='item.id' v-for="item in lists">
						<td>{{item.id}}</td>
						<td>{{item.name}}</td>
						<td>{{item.tester}}</td>
						<td>{{item.project}}</td>
						<td>{{item.project_id}}</td>
						<td>{{item.desc}}</td>
						<td>{{item.create_time}}</td>
						<td>{{item.testcases}}</td>
						<th><button @click="$emit('run',item)">执行</button></th>
					</tr>
				</table>
				`
			})
		
			var vm = new Vue({
				el: '#app',
				data: {
					cases1:[{
							"id": 1,
							"name": "登录接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "登录接口",
							"create_time": "2019-11-06 14:50:30",
							"testcases": 9,
						},
						{
							"id": 2,
							"name": "注册接口_自动化测试平台项目",
							"tester": "可可",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "自动化测试平台项目, 注册接口",
							"create_time": "2019-11-06 14:51:00",
							"testcases": 0,
						}],
					info:''
				},
				methods:{
					// 父组件中监听到子组件触发的事件之后,接收数据的方法
					recvData:function(value){
						console.log(value)
						this.info = value
					}
				}
		
			})
		</script>
		
	</body>
</html>

插槽

一些情况下我们会希望能和 HTML 元素一样向组件中传递内容
父组件在引用子组件时,传递的内容可以使用template标签包裹(通过#slot名的格式指定传递给目标插槽)
子组件使用 <slot> 作为一个占位符(通过value属性给各个插槽分配唯一的 ID,以确定每一处要渲染的内容),父组件传递进来的内容就会渲染在这里

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>

		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<data-views :lists="cases1" @run='recvData($event)'>
				<template slot="title">
					<span>项目名:柠檬班</span>
					<span>版本:V1.0</span>
					<span>时间:2021-04-02</span>
				</template>
				<template slot='body'>
					<h4>python+vue真好用</h4>
				</template>
			</data-views>
			
			
			<hr>
			<div>
				<h3>执行的用例信息:{{info}}</h3>
			</div>
		</div>
		<script type="text/javascript">
			/*
			插槽:定义组件时,给父组件预留填充内容(html)的插口(空白)
			
			*/
			Vue.component('data-views', {
				// 指定父组件中引用该组件时,传递数据的参数名
				props: ['lists'],
				template: `
				<div>
					<slot name='title'></slot>
					<h1>-------------子组件---------------</h1>
					<slot name='body'></slot>
					<table border="" cellspacing="" cellpadding="">
						<tr>
							<th>ID</th>
							<th>接口名</th>
							<th>测试人员</th>
							<th>项目名</th>
							<th>项目ID</th>
							<th>描述信息</th>
							<th>创建时间</th>
							<th>用例数</th>
							<th>操作</th>
						</tr>
						<tr :key='item.id' v-for="item in lists">
							<td>{{item.id}}</td>
							<td>{{item.name}}</td>
							<td>{{item.tester}}</td>
							<td>{{item.project}}</td>
							<td>{{item.project_id}}</td>
							<td>{{item.desc}}</td>
							<td>{{item.create_time}}</td>
							<td>{{item.testcases}}</td>
							<th><button @click="$emit('run',item)">执行</button></th>
						</tr>
					</table>
					</div>
					`
			})

			var vm = new Vue({
				el: '#app',
				data: {
					cases1: [{
							"id": 1,
							"name": "登录接口_自动化测试平台项目",
							"tester": "可优",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "登录接口",
							"create_time": "2019-11-06 14:50:30",
							"testcases": 9,
						},
						{
							"id": 2,
							"name": "注册接口_自动化测试平台项目",
							"tester": "可可",
							"project": "自动化测试平台项目",
							"project_id": 1,
							"desc": "自动化测试平台项目, 注册接口",
							"create_time": "2019-11-06 14:51:00",
							"testcases": 0,
						}
					],
					info: ''
				},
				methods: {
					// 父组件中监听到子组件触发的事件之后,接收数据的方法
					recvData: function(value) {
						console.log(value)
						this.info = value
					}
				}

			})
		</script>
		

	</body>
</html>

单文件组件

<script>
export default {
  data() {
    return {
      greeting: 'Hello World!'
    }
  }
}
</script>

<template>
  <p class="greeting">{{ greeting }}</p>
</template>

<style>
.greeting {
  color: red;
  font-weight: bold;
}
</style>
 


elementUI


前后端交互axios

前端发送请求.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			// 使用axios发送一个get请求
			// const pro = axios.get('http://127.0.0.1:5000/api/projects11')
			// // 此处的res并不是接口的响应  它是一个Promise对象(异步事件的对象)
			// console.log(pro)
			// ----------------获取接口返回的数据(请求成功)-------------------
			// pro.then(function(response){
			// 	// 这个回调函数的中的response才是接口返回的响应对象
			// 	console.log('接口的响应数据:',response)
			// 	// 获取响应体
			// 	console.log(response.data)
			// 	//获取响应的状态码
			// 	console.log((response.status))
			// })
			// console.log('999999999999999999')

			// ----------------获取接口返回的数据(请求失败:返回的状态码是4,5系列的)-------------------
			// pro.catch(function(error) {
			// 	// 获取请求失败的响应对象
			// 	console.log(error.response)
			// 	let response = error.response
			// 	console.log(response.data)
			// 	console.log(response.headers)
			// })


			// 自定义HTTP状态码错误的范围
			const pro = axios.get('http://127.0.0.1:5000/api/projects11', {
				validateStatus: function(status) {
					// 指定HTTP状态码错误的范围
					// return status < 500;
					return true
				}
			})

			pro.then(function(response) {
				// 这个回调函数的中的response才是接口返回的响应对象
				console.log('接口的响应数据:', response)
				// 获取响应体
				console.log(response.data)
				//获取响应的状态码
				console.log((response.status))
			})
		</script>



	</body>
</html>

axios创建请求对象.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			
			
			
			// 使用axios创建请求对象
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: "http://127.0.0.1:5000",
				// 添加固定的请求头
				headers: {
					'X-Custom-Header': 'foobar'
				},
			})

			//使用请求对象
			request.get('/api/projects').then(function(response) {
				console.log(response.status)
			})

			request.get('/api/projects11').then(function(response) {
				console.log(response.status)

			})
		</script>



	</body>
</html>

axios发生get请求的参数传递.html

 <!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			// 使用axios创建请求对象
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: "http://127.0.0.1:5000",
				// 添加固定的请求头
				headers: {
					'X-Custom-Header': 'foobar'
				},
			})
			
			//get方法传递查询字符串参数
			// 方式一 :通过params传递   get('url',{params:{key:value,key:value}})
			//
			// request.get('/api/interface',{
			// 	params:{id:1001}
			// }).then(function(response) {
			// 	console.log(response.status)
			// 	console.log(response.data)
			// })
			// 方式二:直接在url后面拼接  url?key=value&key=value
			//
			// request.get('/api/interface?id=1001').then(function(response) {
			// 	console.log(response.status)
			// 	console.log(response.data)
			// })
			
			
		</script>



	</body>
</html>

json和表单参数的处理.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			// 使用axios创建请求对象
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: "http://127.0.0.1:5000",
				// 添加固定的请求头
				headers: {
					'X-Custom-Header': 'foobar'
				},
			})
			// 发送post请求
			
			// json格式的参数传递: content-Type:application/json
			// request.post('/api/user/login',{user:'python01',pwd:'lemonban'}).then(function(response){
			// 	console.log(response.data)
			// 	console.log(response.status)
			// })

			// 表单参数传递:content-Type:application/x-www-form-urlencoded format
			// 创建表单参数对象
			// const formData = new URLSearchParams();
			// formData.append('user', 'python01')
			// formData.append('pwd', 'lemonban')
			// request.post('/api/user/login', formData).then(function(response) {
			// 	console.log(response.data)
			// 	console.log(response.status)
			// })
			
			
			
		</script>



	</body>
</html>

请求拦截器和响应拦截器.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			
			
			
		
			// 使用axios创建请求对象
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: "http://127.0.0.1:5000",
				// 添加固定的请求头
			})
			
			// 添加请求拦截器:每次请求接口都会自动调用
			request.interceptors.request.use(function (config) {
			    // 在发送请求之前做些什么
				// 接口需要鉴权:token
				console.log('请求拦截器:',config)
			    return config;
			  });

			// 添加响应拦截器:每次请求完之后,A返回响应数据之前会调用。
			request.interceptors.response.use(function (response) {
			    // 对响应数据做点什么
			    return response.data;
				
			  }, function (error) {
			    // 对响应错误做点什么
			    return error.response;
			  });


			//使用请求对象
			request.get('/api/projects').then(function(data) {
				console.log(data)
			})
			

		</script>



	</body>
</html>

async和await的使用.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	</head>
	<body>
		<script type="text/javascript">
			// 使用axios创建请求对象
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: "http://127.0.0.1:5000",
				// 添加固定的请求头
			})

			// 添加请求拦截器:每次请求接口都会自动调用
			request.interceptors.request.use(function(config) {
				// 在发送请求之前做些什么
				// 接口需要鉴权:token
				console.log('请求拦截器:', config)
				return config;
			});

			// 添加响应拦截器:每次请求完之后,A返回响应数据之前会调用。
			request.interceptors.response.use(function(response) {
				// 对响应数据做点什么
				return response;

			}, function(error) {
				// 对响应错误做点什么
				return error.response;
			});


			// 使用请求对象
			// 注意点:await 和只能在通过async定义的函数中使用
			async function getProjec() {
				const response = await request.get('/api/projects')
				console.log(response)
			}
			getProjec()
			
			
			
		</script>



	</body>
</html>

登录案例.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- 引入vue -->
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<!-- axios 用来发送网络请求 -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		<!-- 引入elementUI -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<script src="https://unpkg.com/element-ui/lib/index.js"></script>

	</head>
	<body>
		<div id="app">

			<div class="box" style="width: 600px;height: 400px; margin:100px auto;text-align: center;">
				<el-card class="box-card">
					<h1> 用户登录</h1>
					<el-form ref="formLogin" :model="formLogin" label-width="80px">
						<el-form-item label="账号">
							<el-input v-model="formLogin.user"></el-input>
						</el-form-item>
						<el-form-item label="密码">
							<el-input v-model="formLogin.pwd" type='password'></el-input>
						</el-form-item>
						<el-form-item>
							<el-button type="primary" @click="loginHandle">点击登录</el-button>
						</el-form-item>
					</el-form>
				</el-card>
			</div>
			<hr>
			<button type="button" @click="getProject()">获取所有项目</button>
			<div class="box2">
				  <el-table
				      :data="projects"
				      style="width: 100%">
					  <el-table-column
					    prop="id"
					    label="ID"
					    width="60">
					  </el-table-column>
				      <el-table-column
				        prop="create_time"
				        label="日期"
				        width="180">
				      </el-table-column>
				      <el-table-column
				        prop="name"
				        label="项目名"
				        width="180">
				      </el-table-column>
				      <el-table-column
				        prop="testcases"
				        label="用例数">
				      </el-table-column>
				    </el-table>
			</div>
		</div>
		<script type="text/javascript">
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: 'http://api.keyou.site:8000',

			})

			// 添加请求拦截器:每次请求接口都会自动调用
			request.interceptors.request.use(function(config) {
				// 在发送请求之前,判断是否有token
				if (window.sessionStorage.getItem('token')) {
					config.headers.Authorization = 'JWT ' + window.sessionStorage.getItem('token')
				}
				console.log('请求头', config.headers)
				return config;
			})
			
			var vm = new Vue({
				el: '#app',
				data: {
					formLogin: {
						username: 'musen123',
						password: '1234567'
					},
					projects: [],
				},
				methods: {
					// 点击登录之后,处理登录的方法
					loginHandle: async function() {
						// 请求登录接口
						console.log('请求登录接口')
						const response = await request.post('/user/login/', this.formLogin)
						console.log(response)
						// 判断登录请求是否成功 
						if(response.status ===200){
							alert('登录成功')
							window.sessionStorage.setItem('token', response.data.token)
						}else{
							alert('登录失败')
						}
					},
					getProject: async function() {
						// 请求项目列表
						console.log('请求项目列表接口')
						const response = await request.get('/projects/')
						console.log(JSON.stringify(response.data))
						this.projects = response.data.results
					}
				}

			})
		</script>

	</body>
</html>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- axios 用来发送网络请求 -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		
		<button type="button" onclick="login()"> 登录</button><!-- 
		<button type="button" οnclick="getProject()"> 获取项目</button> -->
	</head>
	<body>
		<script type="text/javascript">
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: 'http://api.keyou.site:8000',

			})

			// 添加请求拦截器:每次请求接口都会自动调用
			request.interceptors.request.use(function(config) {
				// 在发送请求之前,判断是否有token
				if (window.sessionStorage.getItem('token')) {
					config.headers.Authorization = 'JWT ' + window.sessionStorage.getItem('token')
				}
				return config;
			})

			async function login() {
				console.log('请求登录接口')
				const response = await request.post('/user/login/', {
					username: 'musen123',
					password: '1234567'
				})
				console.log(response)
				// 判断登录请求是否成功 
				if (response.status === 200) {
					alert('登录成功')
					window.sessionStorage.setItem('token', response.data.token)
				} else {
					alert('登录失败')
				}
			}

			async function getProject() {
				console.log('请求项目列表接口')
				const response = await request.get('/projects/')
				console.log(JSON.stringify(response.data))
			}

			// // 调用登录函数
			login()

			// // 调用获取项目的函数
			// getProject()
		</script>


	</body>
</html>


路由vue-router

vue-route基本使用

1、初始化路由对象和定义路由对象
2、将路由对象绑定到vue实例中去
3、在根组件中定义路由视图的展示位置

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js" type="text/javascript"></script>
		<!-- 引入vue -->

	</head>
	<body>
		<div id="app">
			
			<!-- <router-link to="/home">主页</router-link> -->
			<!-- <router-link to="/login">登录</router-link> -->
			<!-- 路由视图 -->
			<router-view></router-view>
		</div>

		<script type="text/javascript">
			/*
			第一步:定义展示页面内容的组件
			第二步:定义路由规则
			第三步:初始化路由对象
			第四步:将路由对象绑定到vue实例中去
			第五步:在根组件中定义路由视图的展示位置
			
			注意点:如果在html页面中使用vuerouter  在使用script引入的时候 一定要放在vue下面
			
			路由配置:
				path:指定路由路径
				name:给路由命名
				redirect:指定路由重定向的路径
				component:指定该路由渲染的组件
			
			
			*/

			// 首页
			const home = {
				template: `<h1>这个是项目首页</h1>
				`
			}
			// 登录页面
			const login = {
				template: `
				<h1>这个是项目登录页面</h1>
				`
			}
			// 创建一个路由对象
			const router = new VueRouter({
				//通过路由routes指定路由规则
				routes: [{
						path: '/',
						// 设置路由重定向
						redirect: '/login'
					},
					{
						path: '/login',
						component: login,
						// 给路由设置名字
						name:'login'
					},
					{
						path:'/home',
						component:home
					}

				]
			})


			var vm = new Vue({
				el: '#app',
				// 将路由对象绑定到vue实例中
				router

			});
		</script>



	</body>
</html>

编程式路由和声明式路由

  • 声明式路由

    <router-link :to="{ name: 'user', params: { username: 'erina' }}">
      User
    </router-link>
    
  • 编程式路由

    router.push({ name: 'user', params: { username: 'erina' } })
    
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js" type="text/javascript"></script>
		<!-- 引入vue -->
	</head>
	<body>
		<div id="app">
			<div class="box">
				<!-- 这个路由访问的方式,叫做声明式路由 -->
				<router-link to="/home"><button type="button">用户页面</button></router-link>
				<router-link to="/login"><button type="button">登录页面</button> </router-link>
				<router-link to="/user/1"><button type="button">用户</button> </router-link>
				<router-link to="/user/2"><button type="button">用户</button> </router-link>

				<input type="text" v-model="number">
				<button type="button" @click="handle">提交数据</button>
			</div>

			<router-view></router-view>
		</div>



		<script type="text/javascript">
			// 首页
			const home = {
				template: `<h1>这个是项目首页</h1>
				`
			}
			const cases = {
				template: `<h1>case页面</h1>
				`
			}
			// 登录页面
			const login = {
				template: `
				<h1>这个是项目登录页面</h1>
				`
			}
			const user = {
				template: `
				<h1>这个是项目user页面---{{ $route.params.id }}</h1>
				`
			}
			// 创建一个路由对象
			const router = new VueRouter({
				//通过路由route指定路由规则
				routes: [{
						path: '/login',
						// 给路由设置名字
						name: 'login',
						component: login
					},
					{
						path: '/home',
						component: home
					},
					{
						path: '/case',
						component: cases
					},
					{	//  路由地址上匹配的参数,在路由对应的组件中可以使用 $route.params.参数名  获取
						path: '/user/:id',
						component: user,
						name: 'user'
					},
				]
			})

			var vm = new Vue({
				el: '#app',
				data: {
					number: 0
				},
				methods: {
					handle: function() {
						if (this.number > 5) {
							// 编程式路由
							//跳转到另外一个页面
							this.$router.push({
								name: 'user',
								params: {
									id: this.number
								}
							})
						}
					}
				},
				// 将路由对象绑定到vue实例中
				router

			});
		</script>

	</body>
</html>

登录进入首页案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- 引入vue -->
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<!-- axios 用来发送网络请求 -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		<!-- 引入vue-router用来管理路由 -->
		<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js" type="text/javascript"></script>
		<!-- 引入elementUI -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<script src="https://unpkg.com/element-ui/lib/index.js"></script>

	</head>
	<body>
		<div id="app">

			<router-view></router-view>

		</div>

		<div></div>
		<script type="text/javascript">
			const request = axios.create({
				// 指定请求HTTP响应码错误范围
				validateStatus: function(status) {
					return true
				},
				// 指定基本的url地址
				baseURL: 'http://api.keyou.site:8000',
			})

			// 添加请求拦截器:每次请求接口都会自动调用
			request.interceptors.request.use(function(config) {
				// 在发送请求之前,判断是否有token
				if (window.sessionStorage.getItem('token')) {
					config.headers.Authorization = 'JWT ' + window.sessionStorage.getItem('token')
				}
				console.log('请求头', config.headers)
				return config;
			})


			// 定义组件
			const login = {
				template: `
				<div class="login_box" style="width: 600px;height: 400px; margin: 50px auto;text-align: center;">
					<el-card class="box-card">
						<h1>用 户 登 录</h1>
						<el-form ref="form" :model="formLogin" label-width="80px">
							<el-form-item label="账号">
								<el-input v-model="formLogin.username"></el-input>
							</el-form-item>
							<el-form-item label="密码">
								<el-input v-model="formLogin.password" type='password'></el-input>
							</el-form-item>
							<el-form-item>
								<el-button type="primary" @click="loginHandle">点击登录</el-button>
							</el-form-item>
						</el-form>
					</el-card>
				</div>
				`,
				data() {
					return {
						formLogin: {
							username: '',
							password: ''
						}
					}
				},
				methods: {
					// 点击登录之后,处理登录的方法
					loginHandle: async function() {
						// 请求登录接口
						console.log('请求登录接口')
						const response = await request.post('/user/login/', this.formLogin)
						console.log(response)
						// 判断登录请求是否成功 
						if (response.status === 200) {
							alert('登录成功')
							window.sessionStorage.setItem('token', response.data.token)
							this.$router.push('/home')
						} else {
							alert('登录失败')
						}
					}
				}
			}
			// const home = {
			// 	template: `<div>
			// 	<el-menu
			// 	 @select = 'handle'
			// 	  class="el-menu-demo"
			// 	  mode="horizontal"
			// 	  background-color="#545c64"
			// 	  text-color="#fff"
			// 	  active-text-color="#ffd04b">
			// 	 <el-menu-item index="/cases">用例列表</el-menu-item>
			// 	 <el-menu-item index="/interface">接口列表</el-menu-item>
			// 	 <el-menu-item index="/projects">项目列表</el-menu-item>
			// 	</el-menu>
			// 	<router-view></router-view>
			// 	</div>`,
			// 	methods:{
			// 		handle(index,indexPath){
			// 			console.log(index),
			// 			this.$router.push(index)
			// 		}
			// 	}
			// }
			const home = {
				template: `<div>
				<el-menu
				  :router = 'rou'
				  background-color='#555500'
				  class="el-menu-demo"
				  mode="horizontal"
				  default-active='/cases'	
				  text-color="#fff"
				  active-text-color="#00aaff">
				 <el-menu-item :index="{name:'case'}">用例列表</el-menu-item>
				 <el-menu-item :index="apiListRouter">接口列表1</el-menu-item>
				 <el-menu-item index="/interface">接口列表2</el-menu-item>
				 <el-menu-item index="/projects">项目列表</el-menu-item>
				</el-menu>
				<router-view></router-view>
				</div>`,
				data(){
					return{
						rou : true,
						apiListRouter: {name:'interface'}
					}
				}				
			}

			const project = {
				template: `<div>project </div>`
			}
			const cases = {
				template: `<div> cases</div>`
			}
			const interface = {
				template: `<div>interface</div>`
			}

			// 定义路由规则
			const router = new VueRouter({
				routes: [{
						path: '/',
						redirect: '/home'
					},
					{
						path: '/login',
						component: login
					},
					{
						path: '/home',
						component: home,
						redirect:'/cases',
						children: [{
								path: '/projects',
								component: project
							},
							{
								path: '/cases',
								component: cases
							},
							{
								path: '/interface',
								name: 'interface',										   
								component: interface
							}
						]
					},

				]
			})




			// 添加路由导航守卫
			// 用例对访问的路由进行权限控制
			// 除了login这个路由其他的路由都要进行了登录之后才能访问
			router.beforeEach((to, from, next) => {
				// console.log(to)
				// console.log(from)
				// console.log(next)
				// 判断访问的是否是登录页面
				if (to.path === '/login') {
					return next()
					// 判断当前sessionStorage中是否有token(判断是否登录过)
				} else if (window.sessionStorage.getItem('token')) {
					return next()
				} else {
					return next('/login')
				}
			})



			// 初始vue对象
			var vm = new Vue({
				el: '#app',
				router: router,
				data: {

				},
				methods: {

				}

			})
		</script>




	</body>
</html>


vue-cli

  • 安装vue/cli脚手架
  • 基于脚手架创建vue项目

VUE3

setUp使用

computed使用

  • 多对一,多个数据影响一个
  • 缓存特性,避免每次获取值时都要重新计算
  • 如果属性值是函数,默认使用get方法,函数的返回值就是属性的属性值。还有一个set方法,当数据变化时就会调用set方法
import { ref, reactive, computed } from 'vue'

const loginBtnState = computed(() => {
  const { mobile, loginCode } = phoneForm
  if (mobile.length !== 11 || loginCode.length <= 0) return true
  else return false
})

const loginCodeBtnState = computed(() => {
  if (
    codeTip.value === '验证码' &&
    phoneForm.mobile.length === 11 &&
    /^1[3456789]\d{9}$/.test(phoneForm.mobile)
  ) { return false } else return true
})


const model = computed({
    get() {
      return props.modelValue
    },
    set(val: any) {
      emit('updateModel', val)
    }
  })


# useInit.ts
import { computed } from 'vue'
import { TableOptions } from '../index.types'

export const useInit = (props: Partial<Record<string, any>>) => {
  const tableOption = computed(() => {
    return props.options?.filter((option: TableOptions) => !option.action)
  })

  const actionOption = computed(() => {
    return props.options?.find((option: TableOptions) => option.action)
  })

  const paginationJustify = computed(() => ({
    justifyContent: props.paginationJustify
  }))

  return {
    tableOption,
    actionOption,
    paginationJustify
  }
}

watch使用

  • 一对多,一个数据发生变化,执行相应操作会影响多个数据
  • 允许执行异步操作 ( 访问一个 API )
// 监听当前项目名
watch(
    () => currentProject.value,
    newVal => {
      cache.session.set('project_name', newVal)
    }
)

// 监听项目搜索框内容
watch(
    () => input.value,
    newVal => {
      listProject({name: newVal}).then(response => {
        items.value = response.rows;
      });
    }
)

定义接收属性props

const props = defineProps({
  projectName: {
    type: String,
    default: '请选择项目'
  },
})

定义上报事件emit

const emits = defineEmits(['update:modelValue', 'on-success', 'on-discard']);


父子组件传参

父组件传数据给子组件

  • 父组件在引用子组件时,通过属性绑定的形式(即:自子组件自定义的属性名)传递参数
<Form
        :model-value="formData"
        :options="formOptions"
        label-width="120px" />
  • 子组件在props中声明需要接收的变量名,用props.变量名获取和设置新值(在template部分使用时:可直接使用变量名)
# Form/index.vue

const props = defineProps({
  modelValue: {
    type: Object as PropType<UnwrapNestedRefs<Record<string, any>>>,
    default: () => ({})
  },
  options: {
    type: Array as PropType<FormOptions[]>,
    required: true
  }
});

子组件传数据给父组件

  • 在子组件中使用emit自定义事件,并通过组件绑定的事件,上报自定义事件,把数据传递过去

    const emit = defineEmits(['toIndexCancel', 'checkDetail']);
    const handelCancel = (appointmentId: number) => {
      emit('toIndexCancel', appointmentId);
    };
    const handleClickCheckDetail = (appointmentId: number) => {
      // 查询当前项
      const content = currentList.value.find(item => item.appointmentId === appointmentId);
      emit('checkDetail', content);
    };
    
  • 父组件在引用子组件时,监听子组件自定义的事件,并指定方法去处理这个事件

    @自定义的事件名 = 处理事件的方法
    
    <detail
          ref="detailRef"
          :select-date="currentDate"
          v-model="dialogVisible"
          @checkDetail="handleClickCheckDetail"
          @toIndexCancel="cancel" />
    

    注意:template中使用自定义事件名,可以用“-字母小写"代替"字母大写”,比如 @update:model-value="emit('update:modelValue', false)"

  • 在处理事件的方法中接收数据,并处理

    const handleClickCheckDetail = (item: WorkCalendarItem) => {
      dialogVisible.value = false;
      handleClickContent(item);
    };
    /**
     * 删除预约记录后刷新
     */
    const cancel = () => {
      dialogVisible.value = false;
      queryData();
    };
    


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考 html css js 知识学习代码 源码 提供+源码 供学习参考

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值