WEB入门
WEB的基础知识
前端页面的三大构成
HTML、css、JavaScript
HTML文档——网页
网页:后缀名.html
- 语法:标签(标记)
用尖括号括起来的关键词;
单标签、双标签
单标签: |
双标签:
HTML文档基本结构
<!doctype html> 声明语句
<html> 文档的开始
<!-- html标签和head标签是父子关系(嵌套关系)
head标签和body标签是兄弟关系(并列关系)
-->
<head>
<meta charset="utf-8"> 网页的元信息——编码方式(utf-8)
<title>网页标题</title> 网页标题
</head>
<body>
用户可见
放置标签和文本内容
</body>
</html> 文档的结束
css的引入方式
——内部样式
<head>
<style>
css样式
选择器{
属性名称: 属性值;
}
</style>
</head>
——行间样式
<div style="width: 200px; height: 200px; background-color: red;"></div>
——外部样式
<head>
<link rel="stylesheet" type="text/css" href="css文件的路径">
</head>
JavaScript的引入
——行内
<div style="width: 100px; height: 100px;background-color: red;" onclick="index=0"></div>
——内嵌式
<body>
<script type="text/javascript">
document.write("Hello World!");
</script>
</body>
js的代码是由type决定的;
<script type='javascript'> 默认的
<script type="text/html" > 就是html文件
<script type="text/template"> 模板文件 模板文件是写在HTML中的 模板中尽量套一层顶级div,只能有一个;
——外链式
<script src="js/test.js">
// 外链式的script的标签中不能写内容 (写了也白写)
</script>
js三部曲
- 获取dom操作元素
- 绑定事件
- 具体操作
事件
-
window事件
常用的onload
<script> // window.onload :表示文档中的资源加载完毕(HTML,CSS,图片,音频,视屏等) // onload:资源加载完毕事件 window.onload = function(){ //js代码 document.getElementById("box").onclick = function(){ console.log("我被点击了"); } } </script>
-
js中其它的鼠标事件
- onclick 单击事件
- ondblclick 双击事件
- onmouseover 鼠标移入
- onmouseout 鼠标移出
- onmouseenter 鼠标进入
- onmouseleave 鼠标离开
- oncontextmenu 鼠标右击
- onmousedown 鼠标按下
- onmouseup 鼠标抬起
- onmousemove 鼠标移动
js的dom操作
- 节点的创建
- 元素的创建 document.createElement(“标签名”)
- 文本对象创建 document.createTextNode(“哈哈哈黑黑黑”);
- 节点的添加
- 父元素.appendChild(要添加元素对象); 会在当前父元素的末尾进行添加
- 节点的插入
- 父元素.insertBefore(newEle,oldEle); 在参考元素之前进行插入
- 节点的替换:父元素.replaceChild(newEle,oldEle);
- 节点删除
- 元素对象.remove();移除元素对象
- 父元素.removeChild(移除对象);
- 节点的克隆
- 元素对象.cloneNode(); 默认值是false(可以省略) 只克隆标签本身 不能克隆内容 true:将内容一起进行克隆
- 节点的获取
document.getElementById(“myBtn”)
document.getElementsByTagName(“div”);
document.querySelector(“css选择器”)
JavaScript数据类型
- 基本数据类型
- Number :数字
- String:字符串
- Boolean:布尔
- null:空、空指针(没有指向的地址)
- undefined:未初始化(未赋值)
- 复杂数据类型(引用数据类型)
- object 对象 [包含 Object 对象类 Array 数组类]
- function 函数
es6 symbol
数组api和遍历
- pop();
作用:在数组末尾删除一个数据
是否改变原数组:改变
返回值:返回删除的数据
- shift();
作用:在数组开头删除一个数据
参数:无
是否改变原数组:改变
返回值:返回删除的数据
- indexOf(search,idnex) 首次出现的索引/lastIndexOf(search,index); 最后一次出现的索引
- slice(starIndex,endIndex); 数组截取 endIndex:不包含结束索引
- concat(数据…); 数据的拼接
push 返回值是新数组的长度,修改原数组
作用:在数组末尾增加数据,可以是一个也可以是多个
var a = arr.push(6)
a => 5
arr => [1,2,3,4,6]
+ unshift 返回值是新数组的长度,修改原数组
作用:在数组开头增加数据,可以是一个也可以是多个
+ slice(起始下标,结束下标) 截取数组,返回值是截取的新数组,原数组不变
var a = arr.slice(0,2)
a => [1,2]
arr => [1,2,3,4]
+ splice(删除的起始下标, 删除的个数, 在这个下标处添加的内容)数组的增加 修改 和删除
返回值永远是删除项组成的数组,修改原数组
var a = arr.splice(0,1,5)
a => [1]
arr => [5,2,3,4]
var a = arr.splice(1,0,8)
a => []
arr => [1,8,2,3,4]
遍历
+ forEach 对数组进行遍历
arr.forEach( (item, index) => {})
+ map 对数组进行遍历 , 有返回值 react
var a = arr.map((item, index) => {
return item *= 2
})
a => [2,4,6,8]
+ Filter 对数组进行遍历,按照条件筛选出满足条件的项目,返回一个新的数组
var a = arr.filter((item, index) => {
return item > 2
})
a => [3,4]
+ Some 对数组进行遍历,如果数组内的项目有一个是满足条件的,返回值就是true
var a = arr.some((item, index) => {
return item > 3
})
a => true
+ Every 对数组进行遍历,必须数组内的每一个项目都满足条件的,返回值就是true
var a = arr.every((item, index) => {
return item > 1
})
a => false
+ Find 对数组进行遍历,按照条件进行查找,返回值是第一个满足条件的项目
var a = arr.find((item, index) => {
return item > 1
})
a => 2
+ findIndex对数组进行遍历,按照条件进行查找,返回值是第一个满足条件的项目所对应的下标
var a = arr.findIndex((item, index) => {
return item > 1
})
a => 1
获取dom内容
- 获取原来的内容
var showText = show.innerHTML;//多国际语言使用其赋值内容时翻译为中英文状态会乱码
var showText = show.innerText;
var showText = show.textContent;
表单 xx.value
event事件
- 当dom tree中某个事件被触发的时候,会自动产生一个用来描述事件所有的相关信息的对象,这个对象就是event(事件对象);
- 可通过window.event/event来获取。非IE还可以通过函数传参的形式来使用,一般而言我们使用【形参e或eve】来代替使用;
var oDiv = document.querySelector('div');
oDiv.addEventListener('click',function(e){
console.log(e);
})//可以操作当前事件触发的dom
this的指向
🗣普通函数的this:指向它的调用者,如果没有调用者则默认指向window。需要注意的是:构造函数里的函数的this指向new后的实例,挂载到原型上的普通方法的this指向new后的示例
🗣箭头函数的this:指向它定义时的上下文作用域,而与调用者无关。需要注意的是:挂载到构造函数的原型上的箭头函数仍然取决于定义时的上下文作用域
vue的this指向
如果是vue实例本身的属性和方法,那么this指向就是vue实例本身,比如methods对象,computed对象,watch对象里的方法。
()=>{}箭头函数的方式定义方法,则this指向window,
因为箭头函数中的this指向的是外部函数的this指向,普通函数的this指向的是它的调用者,而vue中的methods和computed和watch他们都是vue本身的方法所以只要他们使用普通函数定义this当然指向他们的调用者即this
vue中this 为undefined解决方法 在函数外 将this赋值为变量 _this=this
var,let,const
let和var的区别var声明变量可以重复声明,而let不可以重复声明,属于TDZ暂时性死区问题;作用域不同,var是函数作用域,而let是块级作用域var可以在声明的上面访问变量,而let不存在变量提升
promise和async
-
async
aa是一个async函数,返回的总是一个promise实例
const aa= async (params, isDetails) => { const { data } = await request.post({xx}) return data } //作者:tanjinrong123 //链接:https://www.jianshu.com/p/8afce082b561 //来源:简书
-
promise
promise是个对象实例,它有3种状态,pending(进行中)、resolved(已成功)、rejected(已失败),这个对象接受一个带有2个函数参数的函数参数a,这两个函数参数是resolve和reject,在a中调用它们就可以改变这个promise对象的状态,我们看到例子中根据请求的返回状态来决定是调用resolve还是reject,promise的状态确定了之后就是不可逆的了,之后的操作就交给了then函数,then接受两个函数对象,分别来处理resolved状态和rejected状态的情况。
const getJSON = function(url) {
return new Promise(function(resolve,reject){
fetch(serverUrl)
.then(response => response.json())
.then(json => resolve(json))
.catch(ex => reject(ex))
});
};
getJSON("/posts.json").then(json=>{
console.log('Contents: ' + json);
}).catch(error=>{
console.error('出错了', error);
});
/***************************async******************************/
async getResultData(url)=>{
const resultData = await getJSON(url).catch((err)=>{
console.log(err)
})
return resultData;
}
getResultData('/posts.json').then((resultData)=>{
console.log('Content:' +json)
})
事件循环中分为宏任务队列和微任务队列
其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行
promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行
async函数表示函数里面可能会有异步方法,await后面跟一个表达式
async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行
localstorage和cookie
localstorage存储大小不同,cookie是4k左右,localStorage是5M左右
2、存储时间不同,cookie会过期,localStorage是永久存储
3、Cookie是老技术,不需要浏览器支持H5,localStorage是H5的技术,需要浏览器支持
4、localStorage是浏览器本地行为,cookie会随着http请求发送给服务器,所以当cookie过大的时候会给请求造成一些影响(请求变慢)5、运用场景不同,cookie是解决http协议的无状态诞生的,localStorage不能解决这个问题,用来存储本地数据
Cookie是将数据存储在客户端浏览器,session将数据存储在服务器端
JQuery
优秀javaScript库,将js中常用的方法进行一定的封装供我们去使用(write less,do more)让开发人员写的更少做的更多
window.onload = function () {
console.log(document.getElementsByTagName("div"));
} //js
$(document).ready(callBack);//jq
var oLis = document.getElementsByTagName("li");
// jQuery对象
var $oLis = $("li");
JQ链式操作
$('div') //找到div元素
.find('h3') //选择其中的h3元素
.eq(2) //选择第3个h3元素
.html('Hello'); //将它的内容改为Hello
.end() //退回到选中所有的h3元素的那一步(当然可以倒退)
注:如果dom是动态渲染的插入的,操作此节点需要查询固定的dom在用find(选择器)查找这个动态节点
WEB框架
VUE
Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
Vue 和 Vue.js
Vue 是一个框架,是一个可以提供完整解决方案的东西
Vue.js 是这个框架的一个核心库
Vue框架:vue.js 组件化 vue路由 vue状态管理
Vue的优缺点
解耦数据 与 视图
组件化便于维护管理
路由
-
只要想让页面发生变化,我们只需要修改数据即可;
-
分离前后端关注点,前端负责界面显示,后端负责数据存储和计算
-
通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件
-
同一套后端程序代码,不用修改就可以用于多种设备客户端
-
用户体验好,快,内容的改变不需要重新加载整个页面
缺点:不支持版本低的浏览器 -
缺点: 不利于SEO优化;第一次加载首页耗时相对长一些
VUE环境
-
安装node环境
安装命令 npm install xxx
-
vue 2.0
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
-
vue安装
npm install vue
-
Vue 提供了一个官方的 CLI
VUE2.X生命周期
created:在created中,data和methods都已经被初始化好了,如果要调用method中的方法,或者操作data中的数据,最早只能在created中
mounted:如果要通过某些插件操作页面上的DOM阶段,最早要在mounted中运行只要执行完mounted,就表示整个VUE实力已经初始化完毕了
destroyed:定时器清除、移除事件监听
插值语法
{{ js表达式 }}
注意:不加引号的都是变量,需要写在data里
基本指令
指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
<p v-if="seen">现在你看到我了</p>
这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。
v-html 是设置innerHTML
v-show 切换元素的显示状态,修改元素 的display,实现显示隐藏,指令后面的内容,最终都会解析为布尔值,值为true元素显示,值为false元素隐藏
V-if v-else-if v-else
v-if与v-show区别
v-show本质就是标签display设置为none,控制隐藏
v-if是动态的向DOM树内添加或者删除DOM元素
v-for 遍历
使用v-for指令时,需要绑定一个:key属性且值是唯一的
数组 v-for=“(item, index) in arr”
+ 对象 v-for=“(value, key, index) in obj”
+ 数字 v-for=“i in 10” i从1开始
一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind
指令可以用于响应式地更新 HTML attribute:
v-bind
<a v-bind:href="url">...</a>
//缩写 <a :href="url">...</a>
V-on:事件类型=“事件处理函数”
<a v-on:click="doSomething">...</a>
//缩写<a @click="doSomething">...</a>
动态属性绑定参数
<a v-bind:[attributeName]="url"> ... </a>
//缩写 <a :[attributeName]="url"> ... </a>
这里的 attributeName
会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。
动态事件
使用动态参数为一个动态的事件名绑定处理函数:
<a v-on:[eventName]="doSomething"> ... </a>
<a @[event]="doSomething"> ... </a>
注:对动态参数的值的约束
动态参数预期会求出一个字符串,异常情况下值为 null
。这个特殊的 null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
对动态参数表达式的约束
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的。
双向数据绑定v-modal
适用于表单标签
<input type="text" v-model="msg">
<select name="" id="" v-model="answer">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<h1>{{answer}}</h1>
原理
<div id="app">
<input type="text" :value="msg" @input="handleInput">
<h1>{{msg}}</h1>
<input type="checkbox" :checked="flag" @change="change">
<h1>{{flag}}</h1>
<select name="" id="" :value="select" @change="handleChange">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<h1>{{select}}</h1>
</div>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data: {
msg: "hello",
flag: true,
select: "C"
},
// 用户在输入框内输入,可以修改msg的值
methods: {
handleInput(e) {
console.log("用户输入了")
this.msg = e.target.value;
},
change(e) {
console.log("flag可以发生改变了")
this.flag = e.target.checked
},
handleChange(e) {
this.select = e.target.value
}
}
})
</script>
双向数据绑定就是一个指令v-model,可以帮助我们获取和设置表单元素的值,他实现的原理是,我看过源码,他首先是判断当前绑定v-model的元素是输入的还是单选多选这种,如果是输入的,实现原理是 value属性值和oninput事件的配合,如果是单选多选这种,实现原理是 checked 和 onchange事件的配合
修饰符
事件修饰符
修饰符告诉 v-on
指令对于触发的事件调用 ,修饰符可以串联
<form v-on:submit.prevent.stop="onSubmit">...</form>
.prevent event.preventDefault() 用于取消事件的默认行为
.stop 阻止事件冒泡(点击子元素父元素也响应,就是冒泡)
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.native 监听自定义标签根标签的事件
v-modal的修饰符
.lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
.number 自动将用户的输入值转化为数值类型
.trim 自动过滤用户输入的首尾空格
键盘事件修饰符
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
<input @keyup.enter="submit">
<input v-on:keyup.13="submit">
<!-- 按下Alt + 释放C触发 -->
<input @keyup.alt.67="clear">
<!-- 按下Alt + 释放任意键触发 -->
<input @keyup.alt="other">
<!-- 按下Ctrl + enter时触发 -->
<input @keydown.ctrl.13="submit">
其余修饰符
.sync 当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。对一个 prop 进行“双向绑定”。
<box :word.sync="wrd" ></box>
VUE模板
<template>
<div>{{msg}}</div>
<!-- <moduleName/> -->
<h1>{{0 | 过滤器名称}}</h1>
</template>
<script>
import moduleName from 'module'
export default {
props:["aa"],//父组件属性
data() {
return {
msg:"hello"
}
},//存放参数
components:{moduleName}, //注册组件
watch: {
// 函数名称,监听的对象
msg() {
// 当msg发生改变就会触发这个函数
},
obj: {
deep: true, // 开启深度监听
// 只有当监听的对象发生改变才会触发hanlder函数
handler() {
console.log("obj改变了")
},
// 当一进入页面,就算没有发生改变,也会先执行一次handler函数
immediate: true
}
},
computed: {
// fullName: function() {}
// fullName: 函数名称, 作为一个值存在
// 触发时机:第一次:如果页面中有使用到该值,页面刷新就触发一次,后续当这个值
// 所依赖的其他值发生了改变,就会重新计算
fullName() {
console.log("触发了")
return this.first + this.last
}
},
methods: {},//函数方法
filters: {
parseStr(val) {
return val+1
}
},//过滤器
}
</script>
<style lang="less" scoped>
//lang-css预处理器,less,sass;scoped杨思仅在当前页面有效
</style>
监听
computed和watch
- watch:用于监听data中的数据变化,只在被监听的属性值发生变化时执行
属性必须在 data 对象上存在,才能让 Vue 转换它,这样才能让它是响应式的
因此,Vue 无法检测到对象属性的添加、删除、修改等操作
默认情况下 handler 只监听对象内部属性的引用的变化
因此,我们只有进行赋值操作的时候,它才会监听到
watch可以直接监听对象的某一个属性值,只能监听原有属性的变化,不能监听新增属性
vue 无法监听 this.$set 修改原有属性的变化
export default {
watch: {
'obj.a': {
handler(newVal){
console.log(newVal)
}
}
},
created(){
// 以下两个都可以监听到 打印两次
this.obj.a = 2
this.obj = { a:2 }
}
}
- computed
不用在data中定义,函数名即为参数
computed:{
getBool(){
return this.age>18?true:false
}
}
- 计算属性和监听器
- 计算属性computed是:监听依赖值的变化
- 只要依赖值不变,都会直接读取缓存进行复用
- 计算属性不能响应异步操作中数据的变化
- 需要人为调用
- 监听器watch是:监听属性值的变化
- 只要属性值发生变化,都可以触发一个回调函数
- 监听器可以响应异步操作中数据的变化
- 自动触发
- 计算属性computed是:监听依赖值的变化
vue的获取页面内容
可以js写法也可以用vue的方法获取页面中的元素
<p ref="myp"></p>
let myp = this.$refs.myp
//替代js的dom查询后续js操作
vue的插件引入
vue项目有个js总文件-main.js 总入口vue文件app.vue ,写的vue文件要在app.vue中引入注册
插件引入
-
js文件直接引入,在index.html中引入
-
npm
-
局部单页面引入
import $ from 'jquery'
-
全局引入放到main.js中
import $ from 'jquery' Vue.prototype.$ = $
-
插槽
组件给预留一个位置,将来调用的时候可以在这个位置放自定义的东西
组件通信
组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。
vue组件间通信的几种方式,如props、$emit
/$on
、vuex、$parent
/ $children
、$attrs
/$listeners
和provide/inject
实现:父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现
父传子通信
父组件
//App.vue父组件
<template>
<div id="app">
<child v-bind:users="arr"></child>//前者自定义名称便于子组件调用,后者要传递数据名
</div>
</template>
<script>
import Users from "./components/child"
export default {
name: 'App',
data(){
return{
arr:["Henry","Bucky","Emily"]
}
},
components:{
child
}
}
子组件
//child子组件
<template>
<div class="hello">
<ul>
<li v-for="user in arr">{{user}}</li>//遍历传递过来的值,然后呈现到页面
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props:{
arr:{ //这个就是父组件中子标签自定义名字
type:Array,
required:true
}
}
}
</script>
总结:父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed
子组件向父组件传值
// 子组件
<template>
<header>
<h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件
</header>
</template>
<script>
export default {
name: 'child',
data() {
return {
title:"Vue.js Demo",
msg:"子向父组件传值"
}
},
methods:{
changeTitle() {
this.$emit("titleChanged",this.msg);//自定义事件 传递值“子向父组件传值”
}
}
}
</script>
// 父组件
<template>
<div id="app">
<child @titleChanged="updateTitle" ></child>//与子组件titleChanged自定义事件保持一致
// updateTitle($event)接受传递过来的文字
<h2>{{title}}</h2>
</div>
</template>
<script>
import Header from "./components/child"
export default {
name: 'App',
data(){
return{
title:"传递的是一个值"
}
},
methods:{
updateTitle(e){ //声明这个函数
this.title = e;
}
},
components:{
"child":child,
}
}
</script>
$emit
/$on
通信
假设兄弟组件有三个,分别是A、B、C组件,C组件如何获取A或者B组件的数据
//main.js
Vue.prototype.Event = new Vue()
<div id="itany">
<my-a></my-a>
<my-b></my-b>
<my-c></my-c>
</div>
<template id="a">
<div>
<h3>A组件:{{name}}</h3>
<button @click="send">将数据发送给C组件</button>
</div>
</template>
<template id="b">
<div>
<h3>B组件:{{age}}</h3>
<button @click="send">将数组发送给C组件</button>
</div>
</template>
<template id="c">
<div>
<h3>C组件:{{name}},{{age}}</h3>
</div>
</template>
<script>
var Event = new Vue();//定义一个空的Vue实例
var A = {
template: '#a',
data() {
return {
name: 'tom'
}
},
methods: {
send() {
this.Event.$emit('data-a', this.name);
}
}
}
var B = {
template: '#b',
data() {
return {
age: 20
}
},
methods: {
send() {
this.Event.$emit('data-b', this.age);
}
}
}
var C = {
template: '#c',
data() {
return {
name: '',
age: ""
}
},
mounted() {//在模板编译完成后执行
this.Event.$on('data-a',name => {
this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
})
this.Event.$on('data-b',age => {
this.age = age;
})
}
}
var vm = new Vue({
el: '#itany',
components: {
'my-a': A,
'my-b': B,
'my-c': C
}
});
</script>
复制代码
provide/inject
允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
// A.vue
export default {
provide: {
name: '浪里行舟'
}
}
// B.vue
export default {
inject: ['name'],
mounted () {
console.log(this.name); // 浪里行舟
}
需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的
// A 组件
<div>
<h1>A 组件</h1>
<button @click="() => changeColor()">改变color</button>
<ChildrenB />
<ChildrenC />
</div>
......
data() {
return {
color: "blue"
};
},
// provide() {
// return {
// theme: {
// color: this.color //这种方式绑定的数据并不是可响应的
// } // 即A组件的color变化后,组件D、E、F不会跟着变
// };
// },
provide() {
return {
theme: this//方法一:提供祖先组件的实例
};
},
methods: {
changeColor(color) {
if (color) {
this.color = color;
} else {
this.color = this.color === "blue" ? "red" : "blue";
}
}
}
// 方法二:使用2.6最新API Vue.observable 优化响应式 provide
// provide() {
// this.theme = Vue.observable({
// color: "blue"
// });
// return {
// theme: this.theme
// };
// },
// methods: {
// changeColor(color) {
// if (color) {
// this.theme.color = color;
// } else {
// this.theme.color = this.theme.color === "blue" ? "red" : "blue";
// }
// }
// }
// F 组件
<template functional>
<div class="border2">
<h3 :style="{ color: injections.theme.color }">F 组件</h3>
</div>
</template>
<script>
export default {
inject: {
theme: {
//函数式组件取值不一样
default: () => ({})
}
}
};
</script>
UI框架
Ant Design Vue
BalmUI
Element+
前端部署
render平台
VUE3.x
vue 2与vue3的区别
1.数据双向绑定原理
Vue2:使用Object.defineProperty()进行数据劫持,结合订阅发布的方式实现。
Vue3:使用Proxy代理,使用ref或者
reactive将数据转化为响应式数据。
2.数据和方法的定义
Vue2:使用选项类型API(OptionsAPI)。Vue3:使用组合型API(CompositionAPI)。
Vue2:
data()(return {};} ,methods:{}
Vue3:
数据和方法都定义在setup中,并统一进行return{}。
3.生命周期不一致
vue3生命周期加个on-* onMounted ,剔除了mounted以前的周期
4.获取props
vue2:console.log(‘props’,this.xxx)
vue3:setup(props,context){ console.log(‘props’,props)}
5.给父组件传值emit
vue2:this.$emit()
vue3:setup(props,context){context.emit()}
3的性能快,体积小,组合api,且已经支持ts语法
VUEX
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
state存储数据
action响应组件
mutations操作数据
getter将state里的数据进行加工
module将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
组件中读取vuex的数据 $store.state.sum
组件中修改vuex的数据: s t o r e . d i s p a t c h ( ′ a c t i o n 中 的 命 名 方 法 ′ , 数 据 ) 或 store.dispatch('action中的命名方法',数据)或 store.dispatch(′action中的命名方法′,数据)或store.commit(‘mutation中的方法’,数据)
注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,直接编写commit
mutation 必须同步执行
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
- Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用
context.commit
提交一个 mutation,或者通过context.state
和context.getters
来获取 state 和 getters。
借助mapstate生成计算属性,从state里面读取数据写法函数括号里 对象或数组
借助mapgetter生成计算属性,从getter里面读取数据写法对象或数组
借助mapmutation生成对应的方法,方法中会调用commit去联系mutations,对象写法,({模板里的函数名:“mutation里面的对应的函数名”}),数组([“mutation里面的对应的函数名”])
借助mapaction生成action对应的方法
模板html里面函数不加括号默认的是省略了括号且里面传入了event参数
nexttick会在dom之后执行,另类setimeout操作
vue router
vue的两个核心是数据驱动和组建系统
vue-router的组件有routerlink,routerview
routerlink相当于a标签进行跳转to跳路径
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<router-link to="/about">Go to About</router-link>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
生成路由实例
import Vue from 'vue'
import Router from 'vue-router'
import Home from "@/components/Home";
import Cart from "../components/Cart";
import My from "../components/My";
import Login from '@/components/Login'
import Order from '@/components/Order'
import Register from '@/components/Register'
Vue.use(Router)
let router= new Router({
routes: [
{
path:'/',
redirect:'/home'
},
{
path: '/home/:uname',
// path:"/home",
name:"home",
component:Home
},
{
path:'/cart',
component:Cart,
meta:{
isCheck:true
},
beforeRouteEnter (to, from, next) {
if(!localStorage.getItem("name")){
setTimeout(() => {
next("/my/login")
}, 1000);
}else{
next()
}
},
},
{
path:'/order',
component:Order,
meta:{
isCheck:true
}
},
{
path:'/my',
component:My,
children:[
{
path:'login',
component:Login
},
{
path:'register',
component:Register
}
]
}
]
})
router.beforeEach((to,from,next)=>{
// if(to.path=="/cart")
console.log(to)
if(to.meta.isCheck){
if(!localStorage.getItem("name")){
setTimeout(() => {
next("/my/login")
}, 1000);
}else{
next()
}
}else{
next()
}
})
export default router
编程式导航
用js去进行页面的跳转和其他操作
this.$router.push(“/home”) 可以后退到上一级页面
this.$router.push({path: “/home”})
{
path: “/home”,
name: “home”,
component: Home
}
this.$router.push({name: “home”})
this.$router.replace(“/home”) 不可以后退到上一级页面
this.$router.back() 浏览器的后退按钮功能
this.$router.forward() 浏览器的前进按钮功能
this.$router.go(n) n如果为正数,则代表前进n个页面,n如果为负数,则代表后退n个页面
路由传参
this.$router.push("/home?id=1&uname=zhangsan")
this.$router.push({path: "/home", query: {
id: 1,
uname: "zhangsan"
}})
this.$router.push({name: "home", query: {
id: 1,
uname: "zhangsan"
}})
// 接
this.$route.query.id
动态路由
{
path: "/home/:uname"
}
// 传
this.$router.push("/home/zhangsan")
this.$router.push({
name: "home",
params: {
id:1
}
})
// 接
this.$route.params.uname
路由守卫
-
全局路由守卫
// 全局路由守卫 // 在进入每一个路由之前回执行这里的回调 router.beforeEach((to, from, next) => { // to 将要访问的路由对象 // from 将要离开的路由对象 console.log(to) // 将要对购物车路由进行拦截,判断当前是否是登录状态 if (to.meta.isCheck) { // 判断登录状态 if (!localStorage.getItem("name")) { setTimeout(() => { next("/my/login") }, 1000) } else { next() } } else { next() } }) router.beforeResolve router.afterEach
每个守卫方法接收三个参数: to: Route: 即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。 next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。 next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。 next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。 next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。 确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。
-
局部路由守卫
{ path: "/cart", component: Cart, meta: { isCheck: true }, // 在进入cart路由之前触发 beforeEnter(to, from ,next) { if (!localStorage.getItem("name")) { next("/my/login") } else { next() } } },
-
组件内守卫
beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate(to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave(to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` }
route配置
-
base
-
默认值:
"/"
应用的基路径。例如,如果整个单页应用服务在
/app/
下,然后base
就应该设为"/app/"
。 -
mode
-
路由使用的模式。
-
类型:
string
-
默认值:
"hash" (浏览器环境) | "abstract" (Node.js 环境)
-
可选值:
"hash" | "history" | "abstract"
配置路由模式:
hash
: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。history
: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。abstract
: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
-
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
滚动行为
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。
axios
import axios from 'axios'
import store from "../store/index.js"
import router from '../router'
let instance =axios.create({
baseURL:'/api',
timeout:6000
})
instance.interceptors.request.use((config)=>{
config.headers.authorization = store.state.user.token
return config
},(err)=>{
Promise.reject(err)
})
instance.interceptors.response.use((res) => {
console.log(res)
if (res.data.code == 403) {
router.push("/login")
}
return res
}, err => {
Promise.reject(err)
})
function get(url,params) {
return instance.get(url,{params})
}
function post(url,data) {
return instance.post(url,data)
}
export default {
get,
post
}
在js中引入封装的请求文件
使用 this.$http.get(url,data).then((res)=>{})
VUE脚手架
npm install -g @vue/cli
- vue -V 测试是否安装成功
- vue create 项目名 (注意不要用中文和特殊字符)
- vue.config.js 配置项目
览器环境) | “abstract” (Node.js 环境)`
-
可选值:
"hash" | "history" | "abstract"
配置路由模式:
hash
: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。history
: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。abstract
: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
滚动行为
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。
axios
import axios from 'axios'
import store from "../store/index.js"
import router from '../router'
let instance =axios.create({
baseURL:'/api',
timeout:6000
})
instance.interceptors.request.use((config)=>{
config.headers.authorization = store.state.user.token
return config
},(err)=>{
Promise.reject(err)
})
instance.interceptors.response.use((res) => {
console.log(res)
if (res.data.code == 403) {
router.push("/login")
}
return res
}, err => {
Promise.reject(err)
})
function get(url,params) {
return instance.get(url,{params})
}
function post(url,data) {
return instance.post(url,data)
}
export default {
get,
post
}
在js中引入封装的请求文件
使用 this.$http.get(url,data).then((res)=>{})
VUE脚手架
npm install -g @vue/cli
- vue -V 测试是否安装成功
- vue create 项目名 (注意不要用中文和特殊字符)
- vue.config.js 配置项目
package.json是项目依赖,打开终端 npm install 安装全部依赖