数据类型
字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
undefined和null 区别
undefined是未定义 不存在的
null 是空值 已定义 typeof得到的是object
javaScript权威指南: null 和 undefined 都表示“值的空缺”,你可以认为undefined是表示系统级的、出乎意料的或类似错误的值的空缺,而null是表示程序级的、正常的或在意料之中的值的空缺。
http 和 https 有何区别
http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。
https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。
常见的HTTP状态码
2开头 (请求成功)表示成功处理了请求的状态代码。
200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
201 (已创建) 请求成功并且服务器创建了新的资源。
202 (已接受) 服务器已接受请求,但尚未处理。
203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。
400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
405 (方法禁用) 禁用请求中指定的方法。
406 (不接受) 无法使用请求的内容特性响应请求的网页。
407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408 (请求超时) 服务器等候请求时发生超时。
409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
mvvm mvc
MVC(Model-View-Controller)
MVC是比较直观的架构模式,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。
MVVM(Model-View-ViewModel)
将“数据模型数据双向绑定”的思想作为核心 View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应view
px em rem的区别 chrome最小字体为12px
px 像素 绝对单位 不会其他元素的尺寸变化而变化
em 根据父元素的字体大小的变化而变化 相对单位
rem 根据根元素的字体大小的变化而变化 相对单位
上下左右居中显示 css
div{
position:absolute;
top:50%;
left:50%
height: 200px;
width:200px;
margin-top:-100px;
margin-left:-100px;
}
margin 实现 必须设置width height
div2{
position:absolute;
top:0;
left:0;right:0;
bottom:0;
margin:auto;
width:200px;
height:200px;
}
清楚浮动
.clear{ clear:both}
父级设置height
父级 overflow:hidden zoom:1
数组去重 遍历数组 indexOf判断是否存在
let arr = [1, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 1, 2, 3, 4], activeArr = []
arr.map((res, index)=> {
if (activeArr.indexOf(res) === -1) {
activeArr.push(res)
}
})
三个盒子,左右定宽,中间自适应 使用flex布局
<style>
.son{
width: 100%;
position:relative;
display: flex;
justify-content: space-between;
height: 50px;
}
.son>div{
margin:0 10px;
background: red;
width: 200px;
}
.dd2{
flex:1
}</style>
<div class="son">
<div class="dd1"></div>
<div class="dd2"></div>
<div class="dd3"></div></div>
eval() 字符串计算函数
console.log(eval('2+2')) 4
console.log(eval('x=2;y=3;x+y')) 5
let num = 9
console.log(eval('num+1')) 10
JS事件冒泡与JS事件代理
事件冒泡 点击子元素触发父元素事件 逐级往上
阻止事件冒泡 :
w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
vue 使用 @click.stop 小程序 bindtap 改成 catchtap
事件委托 将子元素的事件通过冒泡交给父元素执行
CSS样式覆盖规则 !important优先级最高
内联样式 style 权级最大 1000
id 100
class 10
标签 1
继承样式和自身样式 会显示自身样式
!important的样式属性不被覆盖 为特殊 比style还高
box-sizing -moz-box-sizing
盒子组成: 内容 内边距 外边距 边框
box-sizing:border-box 设置盒子固定width height 不受padding影响width
闭包 作用域
闭包
白话文 函数内包有函数 内部函数使用外部函数变量
闭包就是一个函数,捕获作用域内的外部绑定。这些绑定是为之后使用而被绑定,即使作用域已经销毁
闭包的官方定义为:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分
自由变量与闭包的关系是,自由变量闭合于闭包的创建
闭包有三个特性:
函数嵌套函数
函数内部可以引用外部的参数和变量
参数和变量不会被垃圾回收机制回收
作用域
白话文 函数调用外部变量
在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问
函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
浏览器的内核分别是什么?
IE: trident内核
Firefox:gecko内核
Safari:webkit内核
Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核
Chrome:Blink(基于webkit,Google与Opera Software共同开发)
sessionStorage 、localStorage 和 cookie 之间的区别
sessionStorage 本地存储 页面关闭数据及清除 数据可存5M 不同窗口不可共享
localStorage 本地存储 如不主动清除 则一直存在 数据可存5M 窗口可共享
Cookie 数据会发送到服务器端 可设置过期时间 数据不能超过4K, 窗口可共享
函数防抖和函数节流?
函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次
函数防抖的要点,也是要一个setTImeout来辅助实现。延迟执行需要跑的代码
如果方法多次触发,则要把上次记录的延迟执行代码用clearTimeout清掉,重新开始
如果计时完毕,没有方法进来访问触发,则执行代码
clearTimeout(timer);
let timer = setTimeout(function(){
console.log('0')
}, 400);
javascript中的this 指向
全局代码中的this是指向全局对象
作为对象的方法调用时指向调用这个函数的对象
作为构造函数指向创建的对象
require.context()
如页面需要导入多个组件,原始写法:
import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components:{titleCom,bannerCom,cellCom}
大量重复的代码,利用 require.context (需要组件提前预设,在统一的一个文件夹下面)
const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
const name = path.basename(key, '.vue')
modules[name] = files(key).default || files(key)
})
components:modules
VUEX
state:定义存贮数据的仓库 ,可通过this.$store.state 或mapState访问
getter:获取 store 值,可认为是 store 的计算属性,可通过this.$store.getter 或
mapGetters访问
mutation:同步改变 store 值,为什么会设计成同步,因为mutation是直接改变 store 值,
vue 对操作进行了记录,如果是异步无法追踪改变.可通过mapMutations调用
action:异步调用函数执行mutation,进而改变 store 值,可通过 this.$dispatch或mapActions
访问
modules:模块,如果状态过多,可以拆分成模块,最后在入口通过...解构引入
VUE props 和 $attrs(vue2.4) 父组件传子组件 $listeners
主要用于父组件传子组件
props 子组件提前定义获取的父组件传递的参数
$attrs 子组件获取props未定义的父组件传递的参数
$listeners 子组件调用父组件的方法
// 对象
props:{
inpVal:{
type:Boolean, //传入值限定类型
// type 值可为String,Number,Boolean,Array,Object,Date,Function,Symbol
// type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认
required: true, //是否必传
default:200, //默认值,对象或数组默认值必须从一个工厂函数获取如 default:()=>[]
validator:(value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
mounted(){console.log(this.$attrs)}.
// 父组件
<parent @change="change"/>
// 子组件
mounted() {
console.log(this.$listeners) //即可拿到 change 事件
}
Vue $emit 子传父
// 父组件
<parent @change="sonChange">
// 子组件
this.$emit('change','我是子组件的事件')
Vue $children 一级子组件的属性和方法
//父组件
mounted(){
console.log(this.$children)
//可以拿到 一级子组件的属性和方法
//所以就可以直接改变 data,或者调用 methods 方法
}
//子组件
mounted(){
console.log(this.$parent) //可以拿到 parent 的属性和方法
}
vue $refs(父调用子数据) .sync(子动态修改父数据)
// 父组件
<parent ref="parent"/>
mounted(){
console.log(this.$refs.parent) //即可拿到子组件的实例,就可以直接操作 data 和 methods
}
// 父组件
<parent :title.sync="title" />
//编译时会被扩展为
<parent :title="title" @update:title="val => title = val"/>
// 子组件
// 所以子组件可以通过$emit 触发 update 方法改变
mounted(){
this.$emit("update:title", '这是新的title')
}
vue proxy (vue-cli@2.X) 设置代理 允许跨域请求
// config/index.js 约定 /api 进入代理
module.exports = {
dev: {assetsSubDirectory: 'static',
assetsPublicPath: '/',
// 原本proxyTable属性中对象为空,在此进行proxy代理配置(可以跨域)
proxyTable: {
'/api': {
target: 'http://192.168.1.117:8083/', // 后端接口地址 target表示代理的服务器url
changeOrigin: true, // 是否允许跨越
pathRewrite: { // pathRewrite表示路径重写,key表示一个正则,value表示别名
'^/api': '' // // 重写,
}
}
},
// ---------------------------------------------------------host: 'localhost', //
port: 8080, // 开启服务器的端口
autoOpenBrowser: false, // 是否开启在浏览器中打开
errorOverlay: true,
notifyOnErrors: true,
poll: false,
devtool: 'cheap-module-eval-source-map',
cacheBusting: true,
cssSourceMap: true
},build: {
// build时输出的index.html文件,可以自定义路径
index: path.resolve(__dirname, '../dist/index.html'),// build时输出的静态(除了index.html)资源路径
assetsRoot: path.resolve(__dirname, '../dist'),// build时输出静态资源的二级目录
assetsSubDirectory: 'static',// 代表打包后,index.html里面引用资源的的相对地址
assetsPublicPath: './',
// 是否开启cssSourceMap
productionSourceMap: true,
devtool: '#source-map',// 是否开启gzip
productionGzip: false,// 需要用gzip压缩的文件扩展名
productionGzipExtensions: ['js', 'css'],bundleAnalyzerReport: process.env.npm_config_report
}
}
// 接口调用
export const netPictureUpload = (params) =>{
return httpService(`/api/crm/appendix/netPictureUpload`,params,'get'); // 实际路径 crm/appendix/netPictureUpload
}
Vue EventBus
1.就是声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上;
2.类似于 Vuex。但这种方式只适用于极小的项目
3.原理就是利用和emit 并实例化一个全局 vue 实现数据共享
4.可以实现平级,嵌套组件传值,但是对应的事件名eventTarget必须是全局唯一的
// 在 main.js
Vue.prototype.$eventBus=new Vue()
// 传值组件
this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值')
// 接收组件
this.$eventBus.$on("eventTarget",v=>{
console.log('eventTarget',v);//这是eventTarget传过来的值
})
render 函数 slot标签 插槽
1.场景:有些代码在 template 里面写会重复很多,所以这个时候 render 函数就有作用啦
2.render 和 template 的对比
前者适合复杂逻辑,后者适合逻辑简单;
后者属于声明是渲染,前者属于自定Render函数;
前者的性能较高,后者性能较低。
// 根据 props 生成标签
// 初级
<template>
<div>
<div v-if="level === 1"> <slot></slot> </div>
<p v-else-if="level === 2"> <slot></slot> </p>
<h1 v-else-if="level === 3"> <slot></slot> </h1>
<h2 v-else-if="level === 4"> <slot></slot> </h2>
<strong v-else-if="level === 5"> <slot></slot> </stong>
<textarea v-else-if="level === 6"> <slot></slot> </textarea>
</div>
</template>
// 优化版,利用 render 函数减小了代码重复率
<template>
<div>
<child :level="level">Hello world!</child>
</div>
</template>
<script type='text/javascript'>
import Vue from 'vue'
Vue.component('child', {
render(h) {
const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level-1]
return h(tag, this.$slots.default)
},
props: {
level: { type: Number, required: true }
}
})
export default {
name: 'hehe',
data() { return { level: 3 } }
}
</script>
<slot></slot> 为插槽 Vue.component 内使用 例子中slot 代替 Your Profile
<navigation-link url="/channel" loo="asdasd">
Your Profile
</navigation-link>
Vue.component('navigation-link', {
template: `
<div>
Clicking here will send you to
<slot></slot>
</div>
`
})
异步组件 官方文档
项目过大就会导致加载缓慢,所以异步组件实现按需加载就是必须要做的事啦
// 工厂函数执行 resolve 回调
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包, 这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
// 工厂函数返回 Promise
Vue.component(
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
// 工厂函数返回一个配置化组件对象
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
路由的按需加载
{
path:'/',
name:'home',
components:resolve=>require(['@/components/home'],resolve)
}
{
path:'/',
name:'home',
components:()=>import('@/components/home')
}
import()方法由es6提出,import()方法是动态加载,返回一个Promise对象,then方法的参数是加载到的模块。import()方法是异步加载的。
vue context 属性有:
1.props:提供所有 prop 的对象
2.children: VNode 子节点的数组
3.slots: 一个函数,返回了包含所有插槽的对象
4.scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
5.data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
6.parent:对父组件的引用
7.listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
8.injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性
Vue.nextTick
页面加载时需要让文本框获取焦点
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
mounted(){ //因为 mounted 阶段 dom 并未渲染完毕,所以需要$nextTick
this.$nextTick(() => {
this.$refs.inputs.focus() //通过 $refs 获取dom 并绑定 focus 方法
})
}
Vue.filter
// 使用
// 在双花括号中
{{ message | capitalize }}
// 在 `v-bind` 中
<div v-bind:id="rawId | formatId"></div>
// 全局注册
Vue.filter('stampToYYMMDD', (value) =>{
// 处理逻辑
})
// 局部注册
filters: {
stampToYYMMDD: (value)=> {
// 处理逻辑
}
}
// 多个过滤器全局注册
// /src/common/filters.js
let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3')
export { dateServer }
// /src/main.js
import * as custom from './common/filters/custom'
Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))
事件修饰符
.stop:阻止冒泡
.prevent:阻止默认行为
.self:仅绑定元素自身触发
.once: 2.1.4 新增,只触发一次
.passive: 2.3.0 新增,滚动事件的默认行为 (即滚动行为) 将会立即触发,不能和.prevent 一起使用
全局路由钩子 路由守卫 拦截
1.router.beforeEach
router.beforeEach((to, from, next) => {
console.log('全局前置守卫:beforeEach -- next需要调用') //一般登录拦截用这个,也叫导航钩子守卫
if (path === '/login') {
next()
return
}
if (token) {
next();
}
})
2.router.beforeResolve (v 2.5.0+)
和beforeEach类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
即在 beforeEach之后调用
3.router.afterEach
全局后置钩子
在所有路由跳转结束的时候调用
这些钩子不会接受 next 函数也不会改变导航本身
路由模式 Vue.$router Vue.$route
设置 mode 属性:hash或 history
2.Vue.$router
this.$router.push() 跳转到不同的url,但这个方法回向history栈添加一个记录,点击后退会返回到上一个页面
this.$router.replace() 不会有记录
this.$router.go(n) n可为正数可为负数。正数返回上一个页面,类似 window.history.go(n)3.Vue.$route
表示当前跳转的路由对象,属性有:
name:路由名称
path:路径
query:传参接收值
params:传参接收值
fullPath:完成解析后的 URL,包含查询参数和 hash 的完整路径
matched:路由记录副本
redirectedFrom:如果存在重定向,即为重定向来源的路由的名字this.$route.params.id:获取通过 params 或/:id传参的参数
this.$route.query.id:获取通过 query 传参的参数
img 加载失败
// page 代码
<img :src="imgUrl" @error="handleError" alt="">
<script>
export default{
data(){
return{
imgUrl:''
}
},
methods:{
handleError(e){
e.target.src=reqiure('图片路径') //当然如果项目配置了transformToRequire,参考上面 27.2
}
}
}
</script>
deep >>> 深选择器
例如要修改框架内组件的样式
设置scoped的子组件里的元素
<style lang="css" scoped>
.gHeader /deep/ .name{ //第一种写法 color:red; }
.gHeader >>> .name{ //二种写法 color:red; }
</style>
CSS布局之水平垂直居中
元素宽高固定
1.使用absolute 和margin
水平垂直居中的元素设置
{position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
width:100px;
height:100px;}
2.使用absolute 和 calc
水平垂直居中的元素设置
{position: absolute;
top: calc(50% - 50px );
left: calc(50% - 50px );
width:100px;
height:100px;}
元素宽高不固定
1.使用flex
水平垂直居中的父元素设置
{display: flex;
justify-content: center;
align-items: center;}
2.line-height
水平垂直居中的父元素设置
{line-height: 300px;
text-align: center;
font-size: 0px; }
水平垂直居中的元素设置
{font-size: 10px;
display: inline-block;
vertical-align: middle;
line-height:initial;
text-align: left;}
3.使用absolute 和 transform
水平垂直居中的元素设置
{position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);}
4.使用css-table
水平垂直居中的父元素设置
{display:table-cell;
text-align: center;
vertical-align: middle; }
水平垂直居中的元素设置
{display:inline-block;}