赞
踩
在 HTML 页面中的所有元素都可以看成是一个盒子
盒子的组成:内容 content、内边距 padding、边框 border、外边距 margin
盒模型的类型:
标准盒模型
margin + border + padding + content
IE 盒模型
margin + content(border + padding)
控制盒模型的模式:box-sizing:content-box(默认值,标准盒模型)、border-box(IE
盒模型);
!important > 行内样式 > id > 类/伪类/属性 > 标签 > 全局选择器
CSS 的三大特性:继承、层叠、优先级
子元素可以继承父类元素的样式
预处理语言增加了变量、函数、混入等强大的功能
SASS LESS
link连接方式和import导入方式,两者区别如下:
IETest安装之后,即可以使用,可用来检查当前代码在不同浏览器版本中的兼容性
新特性:
浏览器加载页面上引用的CSS、JS文件、图片时,是按顺序从上到下加载的,每个浏览器可以同时下载文件的个数不同,因此经常有网站将静态文件放在不同的域名下,这样可以加快网站打开的速度。
一、存储的时间有效期不同
cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
localStorage的有效期是在不进行手动删除的情况下是一直有效的
二、存储的大小不同
cookie的存储是5kb左右,存储量较小,一般页面最多存储20条左右信息
localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)
三、与服务端的通信
cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信
四、读写操作程度
用法:
bind()函数会创建一个新函数, 为绑定函数。当调用这个绑定函数时,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
事件代理又称之为事件委托。是JavaScript中绑定事件的常用技巧,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡
this 在 JavaScript 中主要有以下五种使用场景。
闭包是指有权访问另一个函数作用域中的变量的函数. 创建闭包常见方式,就是在一个函数内部创建另一个函数.
作用:
我们可以通过Array.prototype.slice.call(fakeArray)将伪数组转变为真正的Array对象: 返回新数组而不会修改原数组
Array.prototype.slice.call(“abc”) ==> [‘a’,‘b’,‘c’]
从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。
以function关键字开头的语句会被解析为函数声明,而函数声明是不允许直接运行的。
只有当解析器把这句话解析为函数表达式,才能够直接运行
(function foo(){
// code..
})()
核心( ECMAScript) , 文档对象模型(DOM), 浏览器对象模型(BOM)
DOM是针对HTML和XML文档的一个API(应用程序编程接口). DOM描绘了一个层次化的节点树, 允许开发人员添加, 移除和修改页面的某一部分.
原始数据类型:
引用数据类型:
Math,Date,Array…
js是一门具有自动垃圾回收机制的编程语言,开发人员不必关心内存分配和回收问题
浅拷贝对原对象或副本的更改可能也会导致其他对象的更改。它实际上只拷贝了一层,并且只当数组和对象包的值是原始值时才会进行拷贝。
let a=[1,2,3]
let b=a;
console.log(b==a)//true
let a=[1,2,3]
let b=[...a]//把数组a的内容 挨个取出 放到b数组中
console.log(b===a) //true
let a=[1,2,3]
let b=a.slice()
console.log(a===b) //false
a[0]=4;
console.log(a)//4 2 3
console.log(b) //1 2 3
let a=[1,2,3]
let b=[]
Object.assign(b,a);
a[0]=4
console.log(a)//4 2 3
console.log(b) //1 2 3
let a=[1,2,3]
let b=Array.from(a)
a[0]=4
console.log(a)//4 2 3
console.log(b) //1 2 3
Javascript对象和数组如果深度嵌套,浅拷贝只能实现第一层的拷贝,但是深度的值依然和原对象共享引用。
let a=[ [1],[2], [3]]
let b=[...a] //浅拷贝
a[0][0]= 4
console.log(a) // [[4],[2],[3]]
consle.log(b) // [[4],[2],[3]] 对象b也被改变了 这时浅拷贝的弊端体现出来了
let a=[ [1],[2], [3]]
let b=JSON.parse(JSON.stringfy(a));
a[0][0]=4;
console.log(a) // [ [4],[2], [3]]
console.log(b) // [ [1],[2], [3]]
let a=[ [1],[2], [3]]
let b=structuredClone(a);
a[0][0]=4;
console.log(a) // [ [4],[2], [3]]
console.log(b) // [ [1],[2], [3]]
const deepCopy=(obj)=>{
if(typeof obj !=='object' || obj == null){
return obj;
}
const newObj= Array.isArray(obj) ? []:{};
Object.keys(obj).forEach((key)=>{
newObj[key]=deepCopy(obj[key]);
})
return newObj;
}
上述代码只能处理对象和数组的深度拷贝
注意理解深拷贝和浅拷贝的区别
原型就是一个普通对象,它是为构造函数的实例共享属性和方法;所有实例中引用
的原型都是同一个对象
使用 prototype 可以把方法挂在原型上,内存值保存一份
__proto__可以理解为指针,实例对象中的属性,指向了构造函数的原型(prototype)
当没有 async 和 defer 这两个属性的时候,浏览器会立刻加载并执行指定的脚本
HTML5 规定的内容:
setTimeout 最小执行时间是 4ms
setInterval 最小执行时间是 10ms
Promise 对象,封装了一个异步操作并且还可以获取成功或失败的结果
Promise 主要就是解决回调地狱的问题,之前如果异步任务比较多,同时他们之间
有相互依赖的关系,就只能使用回调函数处理,这样就容易形成回调地狱,代码的可读性差,可维护性也很差
有三种状态:pending 初始状态 fulfilled 成功状态 rejected 失败状态
状态改变只会有两种情况,
pending -> fulfilled; pending -> rejected 一旦发生,状态就会凝固,不会再变
首先就是我们无法取消 promise,一旦创建它就会立即执行,不能中途取消
如果不设置回调,promise 内部抛出的错误就无法反馈到外面
若当前处于 pending 状态时,无法得知目前在哪个阶段。
原理:
构造一个 Promise 实例,实例需要传递函数的参数,这个函数有两个形参,分
别都是函数类型,一个是 resolve 一个是 reject
promise上还有then方法,这个方法就是来指定状态改变时的确定操作,resolve
是执行第一个函数,reject 是执行第二个函数
token:验证身份的令牌,一般就是用户通过账号密码登录后,服务端把这些凭证
通过加密等一系列操作后得到的字符串
基于 XML 语法格式的图像格式,可缩放矢量图,其他图像是基于像素的,SVG 是
属于对图像形状的描述,本质是文本文件,体积小,并且不管放大多少倍都不会失真
<svg></svg>
<img src="pic.svg" />
http:// www. aaa.com:8080/index/vue.js
协议 子域名 主域名 端口号 资源
同源策略是浏览器的核心,如果没有这个策略就会遭受网络攻击
主要指的就是协议+域名+端口号三者一致,若其中一个不一样则不是同源,会产生
跨域
三个允许跨域加载资源的标签:img link script
跨域是可以发送请求,后端也会正常返回结果,只不过这个结果被浏览器拦截了!
都是应对页面中频繁触发事件的优化方案
系统自带:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
如果给组件加上keep-alive,会额外多
- activated
- deactivated
- beforeCreate
- created
- beforeMount
- mounted
若组件添加keep-alive属性
- beforeCreate
- created
- beforeMount
- mounted
- acitivated
- $el (根节点dom) 产生阶段 : mounted
- $data产生阶段:created
普通组件
- beforeCreate
- created
- beforeMount
- mounted
组件【添加keep-alive属性】
- activated
- 若离开,则执行deactivated
- 是什么
Vue自带的一个组件
功能:用来缓存组件的 【提升性能】- 使用场景【尽量减少发送网络请求与后端交互+反复访问的组件减少其创建次数】
缓存详情页【组件】->在详情页的activated方法中判断之前刷新的参数与当前接收的参数是否一致,如果一致就不刷新数据,否则就发送网络请求刷新数据
v-if 是创建了一个dom节点 如果值为true时 值为false时不创建或者移除该节点
v-show 是直接创建 display:none 隐藏了
- 初次加载v-if比v-show好 页面不会多加载dom盒子
- 频繁切换 v-show比v-if好 创建和删除开销太大,显示和隐藏开销小
- 如果都是值为true,首次加载v-if比v-show快,相同的节点v-show会多加一个display:none=的css属性
v-for 比 v-if 优先级更高 vue.js源码中可以看到 v-for 的分支在v-if之前
- 如果同一个组件 既加了v-for 也加了 v-if 那么速度会下降许多,是先执行v-for渲染列表数据,然后再每个子项都进行v-if判断,增大开销。
- 如果需要判断v-if成立,再执行v-for渲染子项,那么可以使用template模板
<template v-if="condition"> <div v-for="item in list"></div> </template>
- 1
- 2
- 3
- 作用: 用来快速获取dom的,而不用document.getElement*()
- 使用示例:
<img ref="imgref" src="**" id= "img" >
- 1
原生js:
document.getElementById("img")
vue:
this.$refs.imgs
- 作用:获取更新后的dom内容
例如:
<div ref="box" @click="change">{{content}}</div>
...
data(){
return {
content:"old"
}
}
methods:{
change(){
this.str="new";
console.log(this.$refs.box.innerText);//输出old ref中的dom数据未来得及更新
this.$nextTick(()=>{
console.log(this.$refs.box.innerText);//输出new
})
}
}
- 作用:让样式在本组件中生效,不影响其他组件
- 原理:给组件节点新增自定义属性,然后css根据属性选择器添加样式,类似于下面…
<style>
div[data-v-xxx]{
background:red;
}
</style>
...
<div data-v-xxx>sss</div>
<div>bbb</div>
如何让CSS只在当前组件中起作用?
- 给当前组件添加scoped
<style scoped></style>
如果不加,则该css样式全局生效- scss
2.1 先下载npm install sass-loader node-sass --save
2.2 需要给style 添加 属性lang="scss"
<style scoped lang="scss"> $color: red; .warn{ color: $color; } </style>
- 1
- 2
- 3
- 4
- 5
- 6
2.3 scss样式穿透
父元素 /deep/ 子元素 { 新样式 }
- 1
- 2
- 3
例如 修改第三方插件的样式
3. stylus
3.1 下载
npm install stylus stylus-loader --svae
3.2 添加lang属性
<style lang="stylus" scoped> </style>
3.3 stylus样式穿透 [两种方式 deep 或者 >>> ]<style scoped lang="stylus"> 父元素 /deep/ 子元素 { 新样式 } 父元素 >>> 子元素 { 新样式 } </style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 父组件
<Child :data="msg"></Child>
msg和data里面的变量名一致- 子组件
<div>{{data}}</div> export default{ //1. 数组 props:['data'] //2. 对象 props:{ data:String } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 子组件
this.$emit("eventName",value);
- 父组件 在组件中使用 @事件名 绑定子组件的事件到函数
<div @eventName="getVal"></div> ... methods:{ getVal(msg){ this.content=msg; //msg就是子组件传递的内容 } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
通过中转站 eventBus
- 创建bus.js
import Vue from 'vue' export default new Vue;
- 1
- 2
- 发送
import bus from '@/bus' bus.$emit("toBrother",value);
- 1
- 2
- 接收
import bus from '@/bus' mounted(){ bus.$on("toBrother",(data)=>{ this.data=data; //data就是其他兄弟节点传递过来的 }) }
- 1
- 2
- 3
- 4
- 5
- 6
computed 计算属性是有缓存的【只有当计算的内容发生变化时才会重新计算和调用】 例如 return 111 ; 调用三次 也只会调用一次computed方法,因为值不会发生变化。
methods 没有缓存 调用多少次执行多少次
- watch :
1.1 侦听属性 数据或者路由发生了改变才会执行
1.2 一次只能监听单个变量 变化情况 如需要监听多个比较繁琐- computed
2.1 计算的某一个属性的值改变了,计算属性会检测到进行返回。
2.2 computed一个方法可以监听多个相关属性
props是父组件传递进来的,data是组件本身定义的
优先级: props => methods=> data => computed=> watch
代理用于解决开发时的网络跨域问题,可以将所有请求交由proxy去访问
- 创建配置文件 vue.config.js
module.exports = { publicPath:'./', devServer: { proxy: 'http://localhost:3000' // 打包完成后不生效 } }
- 1
- 2
- 3
- 4
- 5
- 6
- 使用时url 不加前面的ip段 直接写接口 如/login
- 如果是开发模式 devServer不适用 会打包后出现异常
打包路径配置
vue.config.js
module.exports = {
publicPath:'./', // 默认为 / 打包后css js等文件的引入地址前缀
}
路由模式:history[默认],hash #
前端如果自己测试项目,用hash
项目上线要求是 history模式,该怎么办?
交给后端进行重定向
开发环境 .env.development
VUE_APP_TITLE=
VUE_APP_ENV='dev'
VUE_APP_BASE_API="http:localhost:3000/"
生产环境 .env.production
VUE_APP_TITLE=
VUE_APP_ENV='pro'
VUE_APP_BASE_API="http:127.0.0.1:3000/"
在axios封装的时候其base_url
let base_url=""
if(process.env.VUE_APP_ENV=='pro'){
base_url=process.baseApi+url;
}else{
// dev模式可以通过代理去访问 直接为默认的url即可
base_url=url;
}
路由模式:history[默认],hash #
区别:
- 表现形式不同
hash模式多了#- 跳转
访问 http:localhost:8888/id
history:会发送请求
hash: 不会发送- 打包后 前端自测要使用hash,如果使用history会出现空白
SPA是什么?单页面应用
缺点:
- SEO优化不好
- 性能不是特别好【需要首页优化】
是 Model-View-ViewModel 的缩写。前端开发的架构模式
M:模型,对应的就是 data 的数据
V:视图,用户界面,DOM
VM:视图模型:Vue 的实例对象,连接 View 和 Model 的桥梁
核心是提供对 View 和 ViewModel 的双向数据绑定,当数据改变的时候,ViewModel
能监听到数据的变化,自动更新视图,当用户操作视图的时候,ViewModel 也可以监听到视
图的变化,然后通知数据进行改动,这就实现了双向数据绑定
ViewModel 通过双向绑定把 View 和 Model 连接起来,他们之间的同步是自动的,
不需要认为干涉,所以我们只需要关注业务逻辑即可,不需要操作 DOM,同时也不需要关
注数据的状态问题,因为她是由 MVVM 统一管理
key 属性是 DOM 元素的唯一标识
作用:
显式传值
==>localhost:8080/about?a=1;
this.$router.push({
path:'/about',
query:{
a:1
}
})
this.$router.push({
path:'/about?a=1'
})
使用query接收值
this.$router.query.a
隐式传值
this.$router.push({
name:'/About',
params:{a:1}
})
接收:
this.$router.params.a
arr.forEach(function(item,index,arr){
console.log(item,index)
})
var newarr = arr.map(function(item){
return item+1
})
3.查找符合条件的元素 对象.filter()
arr.filter(function(item){
if(item > 2){
return false
}else{
return true
}
})
4.查询符合条件的元素,返回索引 对象.findindex()
arr.finindex(function(item){
if(item>1){
return true
}else{
return false
}
})
vue 的特性,用来对文本进行格式化处理
使用它的两个地方,一个是插值表达式,一个是 v-bind
分类:
Vue.filter('add',function(v){
return v < 10 ? '0' + v : v
})
<div>{{33 | add}}</div>
filter:{
add:function(v){
return v < 10 ? '0' + v : v
}
}
全局、路由独享、组件内
- 全局【参数 to from next】
beforeEach、beforeResolve, afterEach- 路由独享
beforeEnter- 组件内【很少】
beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave
const router = new VueRouter({
mode:"history",
base:process.env.BASE_URL,
routes
})
router.beforeEach((to, from,next)=>{
console.log(to,from,next)//to是到哪个页面 from从哪来 next 就是保安
if(有权限){
next() // 放行
}else{
router.push('/login') //转发到其他页面
}
})
在进入某个页面之前进行拦截,可以进行权限判断
场景:详情页(文章,商品)
http://localhost:8080/detail/:id
可以匹配
http://localhost:8080/detail/123
http://localhost:8080/detail/456
Vuex 是一个专门为Vue.js 应用程序开发的状态管理模式
State、Getters、Mutations、Actions、Modules
state 类似于组件中的data,存放数据
getters 类似于组件中的compute
mutations 类似于组建中的methods
actions 提交mutations的
modules 把以上四个属性再细分让仓库更好管理vuex.js
export default new Vuex.Store({ state:{ str:"你好", arr:['a','b','c'] }, getters:{ changeArr(state){ return state.arr.join("=") //和computed一样的缓存效果 } }, mutations:{ toast(state,name){ alert(state.str+name) }, add(){ this.state.num++; } }, actions:{ btnAction({commit,state}){ console.log('actions',state.str,commit) } changeAdd({commit}){ commit('add')//action可以包含异步操作 } }, modules:{} //用于分仓库管理 })
组件[可以多个组件同时使用]:
<div>{{str}}</div> <div>{{arr}}</div> <div>{{changeArr}}</div> <button @click="btn('Lvan')"></button> <button @click="btnAction"></button> <button @click="changeAdd"></button> ... import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' export default{ computed:{ ...mapState(['str','arr']), ...mapGetters(['changeArr']), ...mapMutations(['btn']) }, methods:{ ...mapActions(['btnAction','changeAdd']) } }
定义仓库 cart.js banner.js
export default{
state:{
content:"cart"
},
getters:{...},
mutations:{...},
actions:{...}
}
vuex.js
import car from '*cart.js'
import banner from '*banner.js'
export default new Vuex.Store({
modules:{
car,
banner
}
})
页面上使用
<div>{{content}}</div>
...
<script>
import {mapState} from 'vuex'
export default{
computed:{
...mapState({
content:state=>state.cart.content//导入时需要指定是哪个moudle中的内容
})
}
}
</script>
- action与mutation都是同步事务
- Action提交的是mutaion,而不是直接变更状态
- Action本身可以包含任何异步操作
- 一般不会把方法写到actions里,而是写在mutaions内,异步操作的方法由actions内的方法来commit
- Vuex是单向数据流 不能直接更改,会提示no setters
- 可以通过vuex中mutations中定义方法来修改 有点类似于java中的private属性 未添加setter方法
1.Vuex本身不是持久化存储,重启后数据会回到默认配置内容
2.如果需要做持久化存储,可以使用localStorage或者是vuex-persistexport default{ state:{ num:localStorage.getItem('num')||1 }, mutations:{ add(state){ state.num++; localStorage.setItem(num,state.num); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.vuex-persist使用
3.1 下载 npm install --save vuex-persist
3.2 使用【会自动将vuex中的数据保存到localStorage里面,下次使用直接从本地读取,而不是使用默认值】import VuexPersistence from 'vuex-persist' const vuexLocal=new VuexPersistence({ storage:window.localStorage }) export default{ state:{ num:1 }, mutations:{ add(state){ state.num++; } } modules:{ }, plugins:[vuexLocal.plugin] }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。