Vue
Vue3的一些基本配置
-
去掉ESLint校驗(yàn):
package.json
中的extends去掉eslint:commends -
引入icon圖標(biāo)
// main.js中 import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import * as ElementPlusIconsVue from '@element-plus/icons-vue' const app = createApp(App) for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } // vue頁面使用 <el-icon><edit /></el-icon>
Vuex
- state: 存放數(shù)據(jù)
- mutations: 同步操作,寫方法用于改變state里面的數(shù)據(jù),vue可以監(jiān)聽數(shù)據(jù)的改變進(jìn)行更新(相當(dāng)于methods)
- actions:所有異步操作都放在這里,改變的數(shù)據(jù)不能夠被vue監(jiān)聽
- getters: 進(jìn)行邏輯處理(相當(dāng)于computed屬性)
- module:單一狀態(tài)樹,存放所有模塊
-
新建store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state:{ count: 0 }, mutations:{ // state是必要參數(shù) addCount(state, number){ state.count+=number } }, actions:{ setCount(content, payload){ //增加setCount方法,默認(rèn)第一個參數(shù)是content,其值是復(fù)制一份store,第二個是自定義參數(shù) return new Promise(resolve => { setTimeout(()=>{ content.commit('addCount', payload); resolve(); }, 1000); }) } }, getters:{ // 不能改變state里面的值 alertCount(state){ return `當(dāng)前值${state.count}` } } }) export default store;
-
頁面使用
<template> <div><b>count: {{this.$store.state.count}}</b></div> <button @click="addCount">count++</button> </template> <script> export default { name: 'HelloWorld', mounted() { console.log(this.$store.state.count) // 獲取state值 console.log(this.$store.getters.alertCount) // 執(zhí)行g(shù)etters里的方法 }, methods:{ addCount() { this.$store.commit('addCount', 1) // 執(zhí)行mutation里的方法 } } } </script>
簡寫vuex
- 采用解構(gòu)方法
import {mapState, mapMutations, mapGetters} from "vuex";
<script> import {mapState, mapMutations, mapGetters} from "vuex"; export default { name: 'HelloWorld', mounted() { console.log(this.count) // 解構(gòu)后,采用this.xx調(diào)用vuex的內(nèi)容 console.log(this.name) }, methods:{ ...mapMutations(['addCount']), //mutations和actions要在methods里面解構(gòu) ...mapActions(['setCount']), btnAdd() { this.addCount(1) } }, computed:{ ...mapState(['count', 'name']), //state和getters要在computed里面解構(gòu) ...mapGetters(['alertCount']), } } </script>
- 采用解構(gòu)方法
-
異步action在頁面的使用
async mounted() { console.log(`舊值: ${this.count}`) await this.$store.dispatch('setCount', 3); // 默認(rèn)寫法 await this.setCount(3); // 解構(gòu)寫法 console.log(`新值:${this.count}`) },
v-model低層原理
<h2>v-model低層原理</h2>
<input placeholder="請輸入數(shù)值" id="username" />
<p id="uName"></p>
<script>
let obj={}
Object.defineProperty(obj, 'username', {
// 取值
get:function (){
console.log("取值")
},
// 設(shè)置值
set(val) {
console.log(val)
document.getElementById('uName').innerText = val
}
document.getElementById('username').addEventListener('keyup', function (){
// 監(jiān)聽事件
obj.username = event.target.value;
// console.log(event)
})
</script>
vue理解
- 漸進(jìn)式框架,聲明式渲染,借鑒MVVM思想
- 采用虛擬dom(不會重新渲染所有頁面,先進(jìn)行對比,有更新的部分會進(jìn)行重新渲染(render函數(shù)))
- 高內(nèi)聚,低耦合,使用組件化開發(fā)
- computed屬性:如果多次調(diào)用某個方法,computed里面只會計算一次,減少了資源消
vue2.0生命周期
- 創(chuàng)建前后:組件實(shí)例被創(chuàng)建
- 掛載前后 :組件掛載到實(shí)例
- 更新前后 :組件數(shù)據(jù)更新
- 銷毀前后:組件實(shí)例銷毀
vue性能優(yōu)化
- 數(shù)據(jù)層級不能過深,合理設(shè)置響應(yīng)數(shù)據(jù)
- v-if 和 v-show合理選擇
- 使用數(shù)據(jù)緩存,不頻繁取值、組件緩存(keep-alive)
- 分頁、虛擬滾動
vue組件通信
-
props通信:子組件通過props接受來自父級組件的參數(shù)
-
$emit: 子組件傳遞數(shù)據(jù)給父組件
-
ref:父組件使用子組件的時候設(shè)置ref(ref = ‘foo’),通過 this.$refs.foo 獲取子組件實(shí)例
-
EventBus: 兄弟組件傳值
-
$parent 或 $root: 通過共同祖輩搭建通信橋梁
-
provide 與 inject
父級組件:provide(){ return { foo:'foo' } }
子組件:
inject:['foo'] // 獲取到祖先組件傳遞過來的值
父組件向子組件動態(tài)傳參
需求
- 父組件是文章管理列表,帶有一個編輯按鈕
- 子組件(editor)是一個內(nèi)嵌的富文本編輯器:點(diǎn)擊編輯按鈕,彈出Dialog框,富文本編輯器的內(nèi)容顯示為當(dāng)前文章內(nèi)容(暫且設(shè)為content屬性)
- 我們需要傳遞content屬性到子組件(editor),但是子組件中v-model無法綁定props中的content,因此子組件中的文本內(nèi)容綁定的是data中的html屬性,我們需要將content傳遞并且賦值給html。
當(dāng)前問題
-
按照props傳參(子組件第一次可以接收content并且更新頁面內(nèi)容,當(dāng)時當(dāng)我們點(diǎn)擊編輯其他文章,這時候content雖然有變化,但是無法更新到子組件html屬性上面(相當(dāng)于沒有監(jiān)聽變化),導(dǎo)致頁面無法更新到當(dāng)前文章的content,仍然顯示的是之前的content)
父組件
<el-form-item label="內(nèi)容"> <WangEditor ref="editor" :content="formLabelAlign.content" /> </el-form-item>
子組件
<template> <Editor style="height: 500px; overflow-y: hidden;" v-model="html" :defaultConfig="editorConfig" :mode="mode" @onCreated="onCreated" /> </template> <script> import { Editor, Toolbar } from '@wangeditor/editor-for-vue' export default{ name: 'WangEditor', data() { return { html: this.content, } }, props:['content'], } </script>
解決辦法
在子組件加上content的監(jiān)聽,當(dāng)content變化,再給文本編輯器內(nèi)容綁定的html屬性賦值.
watch:{ content(newVal, oldVal){ console.log('content change') console.log(newVal) this.html = this.content } },
vue-router
1.路由守衛(wèi)
A.全局路由
全局使用
-
router.beforeEach((to, from, next)=>{}):路由跳轉(zhuǎn)前執(zhí)行的操作
to:需要跳轉(zhuǎn)的路徑
from:當(dāng)前頁面路徑
next:執(zhí)行當(dāng)前操作// 登錄攔截器 router.beforeEach((to, from, next) =>{ if(to.path == '/login' || to.path == '/front/home'){ next(); }else{ // 不是登錄頁面 localStorage.getItem("user")?next():next("/login") } })
-
router.beforeResolve
-
router.afterEach((to, from) =>{}):路由跳轉(zhuǎn)后
一般用于跳轉(zhuǎn)后更改頁面標(biāo)題、聲明頁面等輔助功能
B.路由獨(dú)享守衛(wèi)
某個單頁面渲染使用
-
boforeEnter(路由獨(dú)享的守衛(wèi))
const routes = [ { path: '/users/:id', component: UserDetails, beforeEnter: (to, from) => { // reject the navigation return false }, }, ]
C.組件路由
組件渲染的時候使用
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
2.hash和history的區(qū)別
hash模式
-
帶#號,改變URL時,頁面不會重新加載
-
利用window.onhashchange事件實(shí)現(xiàn),每次改變hash值,瀏覽器訪問歷史會新增一個記錄
-
hash值是URL中#后面的值,不會傳遞給服務(wù)器
-
使用"后退"按鈕,返回上一個頁面
history模式
-
通過window.history實(shí)現(xiàn)頁面無刷新跳轉(zhuǎn)
-
路徑會隨http請求發(fā)送給服務(wù)器,因此前端URL必須和請求的后端URL一致,否則404
-
404舉例
當(dāng)我們把 history 項目部署到服務(wù)器中后,此時我們在瀏覽器輸入一個網(wǎng)址(比如是 www.test.com ), 此時會經(jīng)過 dns 解析,拿到 ip 地址后根據(jù) ip 地址向該服務(wù)器發(fā)起請求,服務(wù)器接受到請求后,然后返回相應(yīng)的結(jié)果(html,css,js)。如果我們在前端設(shè)置了重定向,此時頁面會進(jìn)行跳轉(zhuǎn)到 www.test.com/home ,在前端會進(jìn)行匹配對應(yīng)的組件然后將其渲染到頁面上。此時如果我們刷新頁面的話,瀏覽器會發(fā)送新的請求 www.test.com/home, 如果后端服務(wù)器沒有 /home 對應(yīng)的接口,那么就會返回404。
computed和watch的區(qū)別
- computed是計算屬性,函數(shù)內(nèi)的變量可以緩存,除非變量發(fā)生變化,才會重新進(jìn)行計算
- watch主要是監(jiān)聽,每次值變化就會立即進(jìn)行回調(diào)。
v-show和v-if的區(qū)別
- v-show是控制display來讓元素隱藏(會渲染到頁面,不會觸發(fā)生命周期)
- v-if顯示隱藏時是把整個元素刪除(為true才會渲染組件,會觸發(fā)生命周期)
created和mounted請求數(shù)據(jù),有什么區(qū)別
-
created:渲染前調(diào)用,先初始化屬性,再做渲染
-
mounted:渲染完成之后,先初始化頁面,再對元素節(jié)點(diǎn)進(jìn)行操作 (這里請求數(shù)據(jù),可能會出現(xiàn)閃屏問題)
vue中的修飾符
- 事件修飾符
- .stop 阻止冒泡
- .prevent 阻止默認(rèn)行為
- .self 只有在event.target是當(dāng)前元素觸發(fā)
- .capture
- .once 事件只觸發(fā)一次
- .passive 立即觸發(fā)默認(rèn)行為
- 按鍵修飾符
- .keyup .keydown
- 系統(tǒng)修飾符
- 鼠標(biāo)修飾符
- 表單修飾符
keep-alive組件
用來緩存組件 ==》減少頁面刷新、網(wǎng)絡(luò)請求次數(shù),提升性能
Vue el-upload上傳圖片 + express
思路:
- 以formData的數(shù)據(jù)格式上傳圖片
- 后端存儲圖片到文件夾(/images/)下,并且返回給前端圖片名稱(imgUrl)
- 前端通過’http://localhost:3000/images/imgUrl’的形式訪問圖片地址,用于展示
前端代碼
<el-upload
class="avatar-uploader"
action="string"
method="post"
:http-request="uploadImage" // 自定義上傳圖片函數(shù)
>
<img v-if="formLabelAlign.imageUrl" :src="resource+formLabelAlign.imageUrl" class="avatar">
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<script>
export default {
name: "Attractions",
data() {
return {
formLabelAlign: { title: '', date: '', content: '', imageUrl: '', filename: '', label: ''},
resource: 'http://localhost:3000/images/',
}
},
methods: {
uploadImage(params){
// 圖片以formData格式上傳,并且請求頭需要設(shè)置'Content-Type': 'multipart/form-data'
let formData = new FormData()
formData = { file: params.file,}
const config = {
headers:{
'Content-Type': 'multipart/form-data'
}
};
this.request.post('/attractions/uploadImage', formData, config).then(res=>{
// console.log("upload: ", res)
this.formLabelAlign.imageUrl = res.data.data
})
}
},
}
</script>
后端代碼(express)
const MsgCode = require("../config/MsgCode");
const multer = require('multer') // 引入multer:圖片處理的工具包
const path = require('path')
const storage = multer.diskStorage({
// 配置文件上傳后存儲的路徑
destination: function (req, file, cb) {
// NodeJS的兩個全局變量
// console.log("__dirname: ", __dirname); //獲取當(dāng)前文件在服務(wù)器上的完整目錄
// console.log("__filename: ", __filename); //獲取當(dāng)前文件在服務(wù)器上的完整路徑
cb(null, path.join(__dirname, '../public/images'))
},
// 配置文件上傳后存儲的路徑和文件名
filename: function (req, file, cb) {
let defineFilename = new Date().getTime() + file.originalname // 防止圖片名重復(fù)
cb(null, defineFilename)
}
})
const upload = multer({
fileFilter(req, file, callback) {
// 解決中文名亂碼的問題
file.originalname = Buffer.from(file.originalname, "latin1").toString("utf8");
callback(null, true);
},
storage: storage
})
// 上傳首頁圖
router.post('/uploadImage',upload.single('file'), function (req, res, next){
// console.log(req.file)
MsgCode(res, req.file.filename, "") // 返回前端的自定義函數(shù),讀者可以自己使用res.end()進(jìn)行數(shù)據(jù)傳輸
})
this.$nexttick
當(dāng)數(shù)據(jù)被修改后,獲取dom更新之后的數(shù)據(jù),用于異步獲取更新后的數(shù)據(jù),性能優(yōu)化
Object.defineProperty有什么缺點(diǎn)
- 無法監(jiān)聽到數(shù)組變化
- 無法檢測對象屬性的添加和刪除
vue2和vue3區(qū)別
- 選項式API(vue2)和組合式API(vue3)
- vue3:多根節(jié)點(diǎn)
- 響應(yīng)式原理:vue2(Obejct.defineProperty)vue3(proxy)
- Diff算法優(yōu)化
- 虛擬dom增加patchFlag字段
MVC
view(視圖層)-controller(控制器)-model(數(shù)據(jù)模型)
view主要用于UI界面展示和響應(yīng)用戶交互,controller用于監(jiān)聽數(shù)據(jù)改變和處理用戶交互,model用于存放數(shù)據(jù)
MVVM
model-viewmodel-viewcontroller
在MVC的基礎(chǔ)上,把contrler的數(shù)據(jù)和邏輯處理部分抽離出來,放到viewmodel中,是model與controller溝通的橋梁。
JS
JS組成三部分
- ECMAScript: JS的核心內(nèi)容,描述了JS的基礎(chǔ)語法(var for 數(shù)據(jù)類型…)
- 文檔對象模型(DOM)
- 瀏覽器對象模型(BOM): 對瀏覽器窗口訪問和操作
location對象
包含了當(dāng)前url的屬性,主要有
- protocol(‘http:’)協(xié)議
- host(‘www.xx.com’) 網(wǎng)址
- hostname(帶了端口號)
- path (/home/list) 訪問路徑
- search (‘?id=123456&sort=discount’) 參數(shù)
- hash (‘#title’)
innerText 和 innerHTML的區(qū)別
- innerText不識別html標(biāo)簽,不保留空格和換行
- innerHTML識別html標(biāo)簽,保留空格和換行
和=區(qū)別
- ==: 比較的是值(如string類型和number類型比較,會進(jìn)行隱士轉(zhuǎn)化)
- ===:除了比較值,也比較數(shù)據(jù)類型(object類型比較的是地址)
構(gòu)造函數(shù)
- 函數(shù)名首字母大寫
- 不需要return就可以返回結(jié)果
- 調(diào)用函數(shù)必須使用關(guān)鍵字
new
// 構(gòu)造函數(shù)
function Star(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
}
var dz = new Star('DZ', 18, 'male');
console.log(dz.age)
cookie sessionStorage localStorage的區(qū)別
- 三者均保存在本地瀏覽器
- cookie:存儲量小,由服務(wù)器寫入,若設(shè)置了固定的時間,時間過后失效
- session:頁面關(guān)閉自動清除(主要用于檢測用戶刷新頁面)
- localStorage:一直保存在本地(存儲不易變動的數(shù)據(jù)),不會自動清除
token的登錄流程
- 客戶端用賬號密碼請求登錄
- 服務(wù)器驗(yàn)證請求,成功之后,給客戶端簽發(fā)一個token,
- 客戶端將token保存在本地(localstorage或者cookie中)
- 每次客戶端發(fā)送請求,都要攜帶token
- 服務(wù)端收到請求,需要先驗(yàn)證token,驗(yàn)證成功,給客戶端返回請求數(shù)據(jù)
Token存localStorage還是session里面?
- 存localStorage里面,每次請求接口都需要把它當(dāng)做字段傳到服務(wù)器(容易被XSS攻擊)
- 存cookie中,會自動發(fā)送,不能跨域(CSRF攻擊)
基本&引用數(shù)據(jù)類型(JS內(nèi)置對象)
-
基本數(shù)據(jù)類型:string,number,undefined,null,boolean,symbol,bigint
保存在棧內(nèi)存中,保存的是一個值 -
引用類型:object(普通對象)Array Function Date
保存在堆內(nèi)存中,保存的是引用數(shù)據(jù)類型的地址(多個引用會同時改變)。例如下:let obj = { name: 'xm', age: 18 } let obj1 = obj obj1.name = 'change' console.log(obj) console.log(obj1)
常用的對象
- Math(abs, ceil, sqrt, max, min…)
- Date(getYear, getMonth…)
- Array(push, foreach)
- String(concat, length, slice, split)
操作數(shù)組的方法
-
push() pop() sort()
-
splice():數(shù)組刪除,返回刪除的元素,會改變原數(shù)組
-
slice:數(shù)組截取
-
unshift() shift() reverse() concat() join() map() filter() reduce() isArray() findIndex()
-
find 和 filter
find 返回第一個滿足條件的內(nèi)容
filter 返回一個新的數(shù)組let arr = [1, 2, 3, 4, 5, 5] let a = arr.find(item=>item>2) let b = arr.filter(item=>item>2) console.log(a) // 3 console.log(b) // [3, 4, 5, 5]
-
改變原數(shù)組的方法:push() pop() sort() reverse() unshift() shift() splice()
JS判斷數(shù)組的方法
-
Array.isArray() 、instanceof Array() 、 constructor、prototype
let arr = [1, 2,3] let str = 'hello' console.log(Array.isArray(arr)) console.log(arr instanceof Array) console.log(Object.prototype.toString.call(arr).indexOf('Array') > -1) console.log(arr.constructor.toString().indexOf('Array') > -1)
數(shù)組去重
-
Set
-
indexOf
-
filter
let arr = [1, 2, 2, 3, 1, 4] // set去重 console.log(Array.from(new Set(arr))) // indexof去重 function unique(arr){ let brr = [] arr.forEach(item=>{ if(brr.indexOf(item) == -1){ brr.push(item) } }) return brr; } unique(arr) // 方式三:filter var arr2 = arr.filter((item, index,self)=>{ console.log(item, index, self) return self.indexOf(item)===index }) console.log(arr2)
多維數(shù)組最大值
let arr = [
[1, 2,3],
[1,3,5],
[95, 25, 36]
]
let brr = []
arr.forEach(item=>{
console.log(Math.max(...item))
brr.push(Math.max(...item))
})
數(shù)據(jù)類的檢測方法
-
typeof() 判斷基本數(shù)據(jù)類型
-
instanceof() 判斷引用數(shù)據(jù)類型
-
constructor 基本可以判斷基本數(shù)據(jù)類型和引用數(shù)據(jù)類型
console.log(('abc').constructor === String)
-
Object.prototype.toString.call() 可以判斷所有數(shù)據(jù)類型
var opt = Object.prototype.toString console.log(opt.call(2)) // [object Number] console.log(opt.call('abc')) // [object String] console.log(opt.call([])) // [object Array] console.log(opt.call({})) // [object Object] console.log(opt.call(true)) // [object Boolean]
閉包
-
優(yōu)點(diǎn):可以重復(fù)利用內(nèi)部變量,不會污染全局變量,一直保存在內(nèi)存中,不會被垃圾機(jī)制回收
-
缺點(diǎn):閉包較多的時候,會消耗內(nèi)存,導(dǎo)致頁面性能下降,在IE瀏覽器會導(dǎo)致內(nèi)存泄漏
-
應(yīng)用:防抖(防止重復(fù)點(diǎn)擊,n秒后執(zhí)行事件,在n秒內(nèi)重復(fù)點(diǎn)擊,從最后一次點(diǎn)擊開始計時 — 點(diǎn)擊事件)節(jié)流(n秒內(nèi)重復(fù)點(diǎn)擊,只有一次生效 – 滾動條)
-
function fn(){ let name = 'xiaoxie' function getName(){ alert(name) } getName() } fn()
防抖和節(jié)流的實(shí)現(xiàn)
// 防抖:n次內(nèi)重復(fù)點(diǎn)擊,執(zhí)行最后一次
function FD_debounce(func, wait){
let timeout;
return function (){
let context = this; // 保存this指向,context指向當(dāng)前對象
let args = arguments
clearTimeout(timeout)
timeout = setTimeout(function (){
func.apply(context, args);
console.log(context)
}, wait);
}
}
let func = function (){
console.log('我是func')
}
res = {
a: debounce(func, 2000)
}
res.a()
// 節(jié)流: n秒多次點(diǎn)擊,只執(zhí)行一次
function JL_debounce(func, wait){
let timeout;
return function (){
let context = this
if(!timeout){
timeout = setTimeout(function (){
func.apply(context)
timeout = null
}, wait);
}
}
}
內(nèi)存泄漏
JS里已經(jīng)分配內(nèi)存地址對象,但由于長期沒辦法回收和清除釋放,造成長期占有資源的情況,導(dǎo)師運(yùn)行速度緩慢甚至崩潰。
因素
- 未清空的定時器
- 過度的閉包
- 一些元素沒被清除
事件委托(事件代理)
原理:利用事件冒泡的機(jī)制實(shí)現(xiàn),把子元素的事件綁定到父元素身上
父元素添加addEventListener('click', 函數(shù)名, true/false)
默認(rèn)true, false代表阻止(子元素)冒泡
原型鏈
原型鏈:一個實(shí)例對象在調(diào)用屬性和方法的時候,會以此從實(shí)例本身=》構(gòu)造函數(shù)原型 =》原型的原型 去查找
以下例子的原型鏈:p1 -> Person -> Object -> null
原型就是一個普通的對象,它是為構(gòu)造函數(shù)的實(shí)例共享屬性和方法,所有實(shí)例中引用的原型都是同一個對象
<!--原型-->
function Person(){
this.say = function (){
console.log('sing')
}
}
let p1 = new Person()
let p2 = new Person()
p1.say()
p2.say()
例:say調(diào)用了兩次,在內(nèi)存中占用了兩個(如果多次使用,會造成資源浪費(fèi)),為了解決這個問題,原型:將方法掛載到prototype上,所有實(shí)例共享這個方法,減少了內(nèi)存消耗。
__proto__
: 可以理解為指針,實(shí)例對象中的屬性,指向了構(gòu)造函數(shù)的原型(prototype)
p1.__proto__ === Person.prototype // 返回true
例如下:
<!--原型-->
function Person(){
this.say = function (){
console.log('sing')
}
}
Person.prototype.run = function (){
console.log('跑步')
}
let p1 = new Person()
let p2 = new Person()
//p1.say()
//p2.say()
p1.run();
p2.run();
new關(guān)鍵字
實(shí)現(xiàn)new
關(guān)鍵字
function newFun(Fun, ...args){
// 1.創(chuàng)建空對象
let obj = {} // 引用類型
// 2.把空對象和構(gòu)造函數(shù)通過原型鏈進(jìn)行連接
obj.__proto__ = Fun.prototype
// 3.把構(gòu)造函數(shù)的this綁定到新的空對象身上
const res = Fun.apply(obj, args) // 值類型
// 4.根據(jù)構(gòu)造函數(shù)返回的類型判斷,如果是值類型,返回對象;是引用類型,返回這個引用類型
return res instanceof Object ? res:obj;
}
// 測試newFun
function Person(name){
this.name = name
}
Person.prototype.printName = function (){
console.log(this.name)
}
let p1 = newFun(Person, 'xym')
p1.printName()
JS的繼承
-
原型鏈繼承(子類繼承父類,new出來的實(shí)例擁有父類相同的屬性和方法)
缺點(diǎn):無法向父類傳參function Person(){ this.info={ name: '張三', age: 12 } } function Child(){} Child.prototype = new Person();
-
構(gòu)造函數(shù)繼承(使用call / apply 方法實(shí)現(xiàn)繼承,在子類里面調(diào)用父類)
缺點(diǎn):無法實(shí)現(xiàn)函數(shù)的復(fù)用function Person(){ this.info={ name: '張三', age: 12 } } function Child(){ Person.call(this) } let c1 = new Child(); c1.info.nick = 'nick name' console.log(c1.info)
-
組合繼承(調(diào)用了兩次父類構(gòu)造函數(shù))
function Person(gender){ this.info={ name: '張三', gender: gender, age: 19 } } Person.prototype.getInfo = function (){ console.log(this.info) } function Child(gender){ Person.call(this, gender) // 構(gòu)造函數(shù)繼承 } Child.prototype = new Person() // 原型鏈繼承 let c1 = new Child('男') c1.info.nickname = '小張' c1.getInfo() let c2 = new Child('女') c2.info.nickname = '小紅' // c1 和 c2 互不影響 c1.getInfo() c2.getInfo()
-
ES6使用class關(guān)鍵字繼承父類
某些瀏覽器可能不支持class Animal{ constructor(kind) { this.kind = kind } getKind(){ return this.kind } } // 繼承animal類 class Cat extends Animal{ constructor(name) { // 子類構(gòu)造方法必須調(diào)用super方法 super('cat'); this.name = name } getCatInfo(){ console.log(this.name+' : '+this.getKind()) } } let cat = new Cat('buding') cat.getCatInfo()
## JS設(shè)計原理
- JS引擎
- 運(yùn)行上下文
- 調(diào)用棧
- 事件循環(huán)
- 回調(diào)
## JS中的this指向
- 全局對象的this指向window
- 全局作用域/普通函數(shù)中this指向window
- this永遠(yuǎn)指向最后調(diào)用他的對象
- apply call bind可以改變this指向
- 箭頭函數(shù)this指向箭頭函數(shù)外的一層
## setTimeout和setInterval最小時間
- setTimeout 4ms
- setInterval 10ms
## promise
- 解決回調(diào)問題
?```js
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo');
}, 300);
});
myPromise.then(value => {
console.log(value)
})
跨域?如何解決跨域?
跨域:當(dāng)前頁面接口訪問的 協(xié)議/域名/接口 不同,(瀏覽器的同源策略)。(瀏覽器能發(fā)出請求,服務(wù)器能響應(yīng)數(shù)據(jù),返回的時候被瀏覽器攔截了)
解決辦法
- script調(diào)用js文件
- 服務(wù)器實(shí)現(xiàn)cors接口,前端正常訪問就行。服務(wù)器收到前端請求,設(shè)置Access-Control-Allow-Origin
異步操作實(shí)現(xiàn)
-
回調(diào)函數(shù)callback
function f(x){ console.log(x) } function printTime(){ setInterval(function (){ console.log('print fn exe') c = 1 }, 3000) } var c = 0 printTime() f(c)
js內(nèi)部執(zhí)行不是按照順序的,因此這里先打印0,再輸出"print fn exe"。采用回調(diào)函數(shù)實(shí)現(xiàn)異步
<script type="text/javascript"> <!--回調(diào)函數(shù),實(shí)現(xiàn)異步操作--> function f(x){ console.log(x) } function printTime(callback){ setInterval(function (){ console.log('print fn exe') c = 1 callback(c) }, 3000) } var c=0 //方法一 printTime(f) // 方法二 printTime(function (x){ console.log(x) }) </script>
-
async / await
function print(time){ setTimeout(function(){ console.log(time); return 1; },time) } async function fun(){ let a = await print(1000); // let b = await print(3000); // let c = print(2000); console.log(a); // console.log(1) setTimeout(()=>{ alert(a) }, 3000) } fun();
-
setTimeout(利用定時器實(shí)現(xiàn)異步操作)
ES6新特性有哪些?
- 新增了箭頭函數(shù)
不能作為構(gòu)造函數(shù)使用,不能new
沒有arguments
不能用call,apply,bind改變this指向
箭頭函數(shù)的this是在函數(shù)定義時就決定了,不可以修改:this指向定義時外層第一個普通函數(shù)的this - 新增塊級作用域(let 和 const)
不存在變量提升(在變量聲明之后才能使用)
存在暫時性死區(qū)問題
塊級作用域的內(nèi)容
不能在同一個作用域內(nèi)重復(fù)聲明 - Promise
解決回調(diào)地獄問題
自身有all,reject,resolve,race等方法
原型上有then,catch
把異步操作隊列化
三種狀態(tài):pending-初始狀態(tài),fulfilled-操作成功,rejected-操作失敗
async/await
同步代碼做異步操作 - 解構(gòu)賦值
從對象或者數(shù)組中取值,然后給變量賦值 - set和map
set:數(shù)組去重
map的key類型不受影響 - 定義類語法糖(class)
- 數(shù)據(jù)結(jié)構(gòu)(symbol)
- 模塊化(export,import)
call、aply、bind區(qū)別
- 都能改變this的指向
- call和aply功能類似,傳參方法不同
- call傳的是一個參數(shù)列表
- aply傳的數(shù)組
實(shí)現(xiàn)深拷貝
深拷貝就是完全拷貝一個新的對象,會在堆內(nèi)存開辟新空間,拷貝的對象被修改后,原對象不受影響
主要針對引用數(shù)據(jù)類型
-
擴(kuò)展運(yùn)算符
-
JSON.parse(JSON.stringify())
-
遞歸實(shí)現(xiàn)
// 深拷貝 let obj = { name: '張三', age: 18, say(){console.log('say name')}, arr:[[1, 2], 3, 4, 5] } // let obj1 = {...obj} // 方法一:擴(kuò)展運(yùn)算符 // obj1.name = 'xxx' // console.log(obj) // name : "張三" // console.log(obj1) // name : 'xxx' // 方法二:json.parse => 不能拷貝函數(shù),即say沒有拷貝進(jìn)來 // let obj2 = JSON.parse(JSON.stringify(obj)) // obj2.name = 'aaa' // console.log(obj) // console.log(obj2) // 方法三 遞歸實(shí)現(xiàn)深拷貝 function exten(origin, deep){ let res = {} if(origin instanceof Array) res = [] // 判斷數(shù)組, 更改返回類型 for(let key in origin){ let value = origin[key] res[key] = (deep && typeof value == 'object' && value != null) ? exten(value, deep):value } return res } let obj3 = exten(obj, true) obj3.name = 'bbb' obj3.arr[0].push('ccc') console.log(obj) console.log(obj3)
ajax
ajax:交互式網(wǎng)頁開發(fā)技術(shù),在不重新加載整個頁面的情況下,與服務(wù)器交換數(shù)據(jù)并更新部分內(nèi)容
通過XmlHttpRequest對象向服務(wù)器發(fā)送異步請求,然后從服務(wù)器拿到數(shù)據(jù),最后通過js操作dom更新頁面
- 創(chuàng)建XmlHttpRequest對象 xml
- xml.open()和服務(wù)器建立連接
- xml.send()發(fā)送數(shù)據(jù)
- xml.onreadystate() , xml.change()事件監(jiān)聽服務(wù)器和通信狀態(tài)
- 接收并處理服務(wù)器響應(yīng)的數(shù)據(jù)
- 更新數(shù)據(jù)到html頁面
ajax/fetch/axios區(qū)別
- fetch是es6的一個用于網(wǎng)絡(luò)請求的api
- axios是一個網(wǎng)絡(luò)請求庫
- ajax是異步j(luò)s和xmlhttprequest
axios封裝
vue2.0
npm install axios // 安裝
-
創(chuàng)建service.js配置文件
import axios from 'axios' import { Message, Loading } from 'element-ui' const ConfigBaseURL = 'http://localhost:8080/' //默認(rèn)路徑,這里也可以使用env來判斷環(huán)境 let loadingInstance = null //這里是loading //使用create方法創(chuàng)建axios實(shí)例 export const Service = axios.create({ timeout: 7000, // 請求超時時間 baseURL: ConfigBaseURL, method: 'post', headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) // 添加請求攔截器(請求前執(zhí)行) Service.interceptors.request.use(config => { loadingInstance = Loading.service({ lock: true, text: 'loading...' }) return config }) // 添加響應(yīng)攔截器(服務(wù)器響應(yīng)后執(zhí)行) Service.interceptors.response.use(response => { loadingInstance.close() return response.data }, error => { console.log('TCL: error', error) const msg = error.Message !== undefined ? error.Message : '' Message({ message: '網(wǎng)絡(luò)錯誤' + msg, type: 'error', duration: 3 * 1000 }) loadingInstance.close() return Promise.reject(error) })
-
main.js
使用import {Service} from '@/utils/service' Vue.prototype.request = Service //將axios放在vue的this上(vue2) app.config.globalProperties.request = Service //(vue3)
-
使用
// post方法 this.request.post(`/menu/delete?id=${val}`).then(res=>{ // 請求成功 }else{ // 請求失敗 } }); // get方法 this.request.get("/echarts/getList").then(res =>{ console.log(res) })
vue3.0
-
創(chuàng)建
http.js
import axios from "axios";//創(chuàng)建一個axios的對象 //生成一個axios的實(shí)例 const http=axios.create({ baseURL:"http://localhost:8080/",// baseURL會在發(fā)送請求的時候拼接在url參數(shù)前面 timeout:3000,//請求超時 }); export default http;//導(dǎo)出
-
main.js
使用import axios from "axios"; const app = createApp(App) app.config.globalProperties.axios = axios
-
單頁面使用
getWeather:function (){ this.axios.get(url).then(res =>{ // console.log(res) }) }
-
封裝API的js文件使用(異步調(diào)用)
封裝函數(shù)js文件import http from "./http"; export const getWeather = ()=>{ return new Promise((resolve, reject)=>{ http.get(url).then(res =>{ resolve(res) }) }) }
頁面調(diào)用
// 1.引入 import {getWeather} from '../request/HomeHeader.js' // 2.獲取返回值 let res = getWeather() // 方法一 采用promise實(shí)現(xiàn)異步 res.then((res)=>{ console.log(res) }) // 方法二 采用async/await實(shí)現(xiàn)異步 async created() { let res = await getWeather() console.log(res) }
get和post請求
- get是請求數(shù)據(jù),post是提交數(shù)據(jù)
- get的請求參數(shù)放在url中,不安全,post請求參數(shù)放在body中
- get請求會緩存,post不會緩存
- 刷新或回退頁面get不會重新請求,post會重新請求
- get請求只能進(jìn)行url編碼,post支持多種編碼方式
promise和async/await的區(qū)別是什么
- 都是處理異步請求的方式
- async/await是基于promise實(shí)現(xiàn)的
- promise是返回對象,使用then,catch方法處理和捕獲異步請求,鏈?zhǔn)綍鴮?,造成代碼重疊,維護(hù)差
- async/await使用try,catch捕獲異常
SVG格式
基于XML語法的圖像格式,可縮放矢量圖,本質(zhì)是文本文件,無論縮放都不會失真
JWT
JSON Web Token 通過JSON形式作為在web應(yīng)用中的令牌
JWT認(rèn)證流程
- 前端發(fā)送登錄請求給接口
- 服務(wù)器核對賬號密碼成功,把用戶id等信息作為jwt負(fù)載,和他和頭部進(jìn)行base64編碼,形成jwt
- 前端每次請求都會把jwt放在http請求頭的Authorization字段內(nèi)
- 服務(wù)器驗(yàn)證jwt的有效性,返回對應(yīng)結(jié)果
JSON
JSON是一種純字符串形式的數(shù)據(jù),適合網(wǎng)絡(luò)傳輸
- JSON.parse()
- JSON.stringfy()
數(shù)據(jù)沒有請求過來時,該怎么做?
給數(shù)據(jù)設(shè)默認(rèn)值,最后進(jìn)行判斷
無感登錄
用戶不需要重新登錄,優(yōu)化用戶體驗(yàn)
方案如下
- 在響應(yīng)器中攔截,判斷token過期后,調(diào)用刷新token的接口
- 后端返回過期時間,前端判斷token過期時間,去調(diào)用刷新token的接口
- 設(shè)置定時器,定時刷新token
大文件上傳
采用分片上傳思想
- 把文件按照一定規(guī)則分塊,分割成相同大小的數(shù)據(jù)
- 初始化一個分塊上傳,返回本次上傳唯一標(biāo)識
- 按照一定規(guī)則把各個數(shù)據(jù)上傳
- 服務(wù)器判斷文件完整性,完整就把文件塊合并
斷點(diǎn)續(xù)傳
JS為什么是單線程
為什么是單線程:比如當(dāng)一個用戶執(zhí)行添加節(jié)點(diǎn)和刪除節(jié)點(diǎn)的任務(wù),如果不是單線程,則會出問題
JS微任務(wù)和宏任務(wù)
-
js是單線程的
-
js代碼執(zhí)行流程:同步執(zhí)行完 ==》事件循環(huán)[微任務(wù)、宏任務(wù)] ==》微任務(wù) ==》宏任務(wù) ==》微任務(wù) …
for(let i=0; i<3; i++){ setTimeout(function (){ console.log(i) }, 1000*i) } // 輸入三個3
-
微任務(wù):promise.then
-
宏任務(wù):setTimeOut
JS作用域
-
除了函數(shù)外,js無塊級作用域
-
作用域鏈:內(nèi)部可以訪問外部變量,但外部不能訪問內(nèi)部
注:如果內(nèi)部有相同的變量,則優(yōu)先訪問內(nèi)部的變量let a = 10; function fun(){ let a = 20; console.log(a) } fun();
-
js變量提升機(jī)制
function c(){ var b = 1; function a(){ console.log(b) //undifined var b = 2; console.log(b) // 2 } a() console.log(b) // 1 } c()
-
優(yōu)先級:聲明變量 > 聲明普通函數(shù) > 參數(shù) > 變量提升
JS對象
-
對象都是new構(gòu)建的,所以對象之間不相等
console.log([1,2,3] === [1,2,3]) // false
-
對象的key都是string類型
-
原型鏈:對象本身obj ==》構(gòu)造函數(shù)Fun =》對象的原型(
obj._proto_
) =》構(gòu)造函數(shù)的原型(Fun.prototype) => Object => null
var let const的區(qū)別
-
let const 不存在變量提升,var有
-
var可以聲明同一個變量多次,let const 只能聲明一次同一個變量
-
const聲明常量,一旦賦值不可以修改(const為object/數(shù)組,里面的值是可以修改的)
-
let const有塊級作用域
if(true){ let a = 1; const b = 2; var c = 3; } console.log(c) // c能打印,a,b會報錯 console.log(a) console.log(b)
object對象的合并
const a = {a:1, b:4}
const b = {b:2, c:3}
//方式1
let obj = Object.assign(a, b) // {1,2,3}
// 方式二
let obj2 = {...a, ...b} // {1,2,3}
websocket(vue2.0實(shí)現(xiàn))
-
前端
登錄頁:輸入用戶信息,進(jìn)入聊天室
聊天頁:輸入消息,點(diǎn)擊按鈕發(fā)送<template> <div> <ul> <!-- 消息展示 --> <li v-for="item in msgList" :key="item.id"> <div>用戶:{{item.username}}</div> <div>時間:{{new Date(item.dateTime)}}</div> <p>消息:{{item.msg}}</p> </li> </ul> <input type="text" placeholder="請輸入消息" v-model="msg"> <button @click="sendMsg">發(fā)送</button> </div> </template> <script> // npm install ws const ws = new WebSocket('ws://localhost:8080') export default { name: "Two", data(){ return{ msg: '', username: '', msgList: [] } }, methods:{ sendMsg(){ const msg = this.msg ws.send(JSON.stringify({ id: new Date().getTime(), username: this.username, dateTime: new Date().getTime(), msg: this.msg })) }, handleWsOpen(e){ console.log('websocket open', e) }, handleWsClose(e){ console.log('websocket close', e) }, handleWsError(e){ console.log('websocket error', e) }, // 接收消息 handleWsMessage(e){ // console.log('websocket message', e) let msg = JSON.parse(e.data) this.msgList.push(msg) console.log(msg) }, }, mounted() { this.username = localStorage.getItem('username') if(!this.username){ this.$router.push('/login') } // 事件綁定 ws.addEventListener('open', this.handleWsOpen.bind(this), false); ws.addEventListener('close', this.handleWsClose.bind(this), false); ws.addEventListener('error', this.handleWsError.bind(this), false); ws.addEventListener('message', this.handleWsMessage.bind(this), false); } } </script> <style scoped></style>
-
后端
新建index.js文件const Ws = require('ws') // 立即執(zhí)行函數(shù) ;((Ws)=>{ const server = new Ws.Server({port: 8080}); // 要和前端監(jiān)聽同一個端口 // 初始化函數(shù) const init = ()=>{ bindEvent(); } function bindEvent(){ server.on('open', handleOpen); server.on('close', handleClose); server.on('error', handleError); server.on('connection', handleConnection); } function handleOpen(){ console.log('wb open') } function handleClose(){ console.log('wb close') } function handleError(){ console.log('wb error') } // 消息接收 function handleConnection(ws){ console.log('wb connection') ws.on('message', handelMsg) } // 消息處理 function handelMsg(msg){ // c : 表示每個客戶端 let oMsg = msg.toString() server.clients.forEach((c)=>{ c.send(oMsg) }) } init() })(Ws);
HTTP協(xié)議以及瀏覽器原理
http協(xié)議
web端發(fā)送請求報文(請求頭、URL、請求方法、請求數(shù)據(jù)、協(xié)議版本) ==》 服務(wù)器端返回數(shù)據(jù)(響應(yīng)頭、協(xié)議版本、響應(yīng)數(shù)據(jù)、響應(yīng)代碼(success/error)、服務(wù)器信息)
http協(xié)議是無狀態(tài)協(xié)議 導(dǎo)致了 cookies的產(chǎn)生(用于驗(yàn)證服務(wù)器的合法性)
http協(xié)議版本
- 1.0 只能
- 1.1
- 2.0
瀏覽器原理
- 輸入網(wǎng)址
- DNS域名解析(有該網(wǎng)頁則返回,沒有返回錯誤信息)
- TCP三次握手(建立連接)
- HTTP請求(獲取資源) =》 HTTP響應(yīng)
- 瀏覽器渲染頁面。HTML解析 =》 DOM樹,css =》css規(guī)則樹,兩者結(jié)合渲染成render樹,瀏覽器通過render對頁面進(jìn)行渲染布局
http緩存
- 強(qiáng)緩存(本地緩存)和協(xié)商緩存(弱緩存)
- 網(wǎng)頁請求資源
- 沒有緩存 =》 使用服務(wù)器資源 =》返回請求資源。
- 有緩存 =》強(qiáng)緩存命中 =》使用緩存內(nèi)容 =》返回資源。
- 強(qiáng)緩存未命中 =》協(xié)商緩存命中,使用緩存內(nèi)容;未命中 =》服務(wù)器資源 =》返回資源
瀏覽器如何渲染頁面
- html解析成DOM樹,CSS解析成CSS規(guī)則樹
- 瀏覽器將CSS規(guī)則樹附著在DOM樹上,結(jié)合生成Render渲染樹
- 生成布局:瀏覽器解析渲染樹節(jié)點(diǎn)的位置和大小,在屏幕上渲染出所有節(jié)點(diǎn)(重排)
- 將布局繪制在屏幕上,生成整個頁面(重繪)
Http請求頭和響應(yīng)頭
- 請求頭
- Accept(瀏覽器可接受服務(wù)器返回數(shù)據(jù)類型, text/html, ‘/’ 代表所有)
- Accept-Encoding(gzip, deflate 申明瀏覽器接受的編碼方法)
- Connection(keep-alive / close , 當(dāng)瀏覽器與服務(wù)器建立了TCP連接,keep-alive表示不斷開,下次請求服務(wù)器使用相同的TCP連接)
- Host(服務(wù)器ip和端口)
- Referer(瀏覽器的地址)
- User-Agent(瀏覽器的操作系統(tǒng)和名稱、版本)
- Cookie(存儲用戶信息)
- 響應(yīng)頭
- Content-Type(
Content-Type:text/html;charset=UTF-8
):資源文件的類型以及編碼方式 - Content-Encoding: 編碼格式
- Date:服務(wù)器時間
- Server:服務(wù)器信息
- Connection(keep-alive/ close)
- Access-Control-Allow-Origin:指定可以訪問服務(wù)器的網(wǎng)址(
Access-Control-Allow-Origin: *
代表所有網(wǎng)站可以跨域資源共享) - Access-Control-Allow-Methods(GET, POST, DELETE, PUT)
- Access-Control-Allow-Credentials(是否允許發(fā)送cookie)
- Content-Type(
同源策略
協(xié)議(http)+域名(www.a.com)+端口號(8080)三者一致,其中一個不同就不是同源,需要跨域
跨域的方法
- JSONP(利用script標(biāo)簽不存在跨域的方式)
- CORS(服務(wù)器配置響應(yīng)頭
Access-Control-Allow-Origin
) - websocket
- 反向代理(中間件)
CSS
BFC(塊級格式化上下文)
- bfc就是一個隔離容器,日期里面的子元素不會影響到外面的元素
- bfc的原則:如果一個元素具有bfc,那么內(nèi)部元素任何操作都不會影響到外部元素
- 如何觸發(fā)bfc(一般給內(nèi)部元素加overflow:hidden):
float:none
overflow: visible
display:inline-block、table-cell
position: absolute、fixed
清除浮動有哪些方式
// li標(biāo)簽會自己浮動,沒有包裹在ul標(biāo)簽里面
<style>
*{margin: 0; padding: 0}
ul{
list-style: none;
border: 10px solid red;
}
li{
width: 100px;
height: 100px;
background: yellow;
float: left;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
// 方法1:觸發(fā)bfc清楚浮動
ul{
overflow: hidden;
}
// 方法2:after方式
ul:after{
content: '';
display: block;
clear: both;
}
position有哪些值,分別根據(jù)什么定位
- static:默認(rèn)值,代表沒有定位
- fixed:固定定位,相對于瀏覽器窗口進(jìn)行定位,(使用left,right, top,bottom)
- absolute:相對于第一個有relative父元素定位
- relative:相對定位,相對于自身定位,不脫離文檔流(位置改變了,其原有位置不會被其他元素占據(jù))
flex布局
flex 表示 flex-grow(設(shè)置擴(kuò)展比例), flex-shrink(設(shè)置收縮比例), flex-basis(不伸縮的情況下子容器的原始尺寸)
flex:1
: (1, 1, 0%) 不管內(nèi)容多少,都是平分空間
flex:auto
: (1, 1, auto) 根據(jù)內(nèi)容的大小來分,不是均分的(除非內(nèi)容都是一樣,才均分)
flex:0
: (0, 1, 0%)可縮小,不可擴(kuò)大
flex:none
:(0, 0, auto) 不可擴(kuò)大 不可縮小
CSS樣式優(yōu)先級(權(quán)重)
- !import > 行內(nèi)樣式 > id選擇器 > class選擇器 > 標(biāo)簽選擇器 > 通配符
盒子模型
在html頁面中所以元素都可以看成是一個盒子
盒子組成
- 內(nèi)容content
- 內(nèi)邊距padding
- 邊框border
- 外邊距margin
盒模型類型
- 標(biāo)準(zhǔn)盒模型 margin+border+padding+content
- IE盒模型 margin+content(padding + border)
控制盒模型的模式:box-sizing:content-box(默認(rèn)值), border-box(IE盒模型)
隱藏元素的方法
- display: none(元素消失,不占空間)
- opacity: 0 (透明度,占空間)
- visibility: hidden(元素消失,占空間)
- position: absolute(將元素移除頁面)
- clip-path(將元素剪掉)
px和rem區(qū)別
- px: 像素,絕對單位長度,每個顯示器像素大小一樣
- rem:相對單位,相對html根節(jié)點(diǎn)font-size的值改變,html的根節(jié)點(diǎn)默認(rèn)16px :
font-size = 62.5%
=>1rem = 10px
(16px * 62.5% = 10px) - em: 相對父元素的font-size改變
重繪和重排(回流)
- 重排(回流):布局引擎根據(jù)所有樣式計算出盒模型在頁面的位置和大小
- 重繪:計算好盒模型在頁面的位置和大小以及其他屬性,然后根據(jù)每個盒模型的特性進(jìn)行繪制
- 對DOM的大小、位置修改,重排
- 對DOM的樣式修改,重繪
元素水平居中方式
- 定位+margin
- flex布局
- grid布局
- table布局
例:
<div id="app">
<div id="sub"></div>
</div>
<!-- 定位+margin -->
#app{
width: 400px;
height: 400px;
position: relative;
border: 3px solid royalblue;
}
#sub{
position: absolute;
width: 100px;
height: 100px;
background-color: red;
top: 0;
right: 0;
left: 0;
bottom: 0;
margin: auto;
}
H5C3新特性
H5新特性
- 語義化標(biāo)簽
- 新增音頻視頻
- 畫布canvas
- localStorage和sessionStorage
- 表單控件email url search
- 拖拽釋放api
css3的新特性
- 選擇器:屬性選擇器、偽類選擇器、偽元素選擇器
- 增加了媒體查詢
- 文字陰影
- 邊框
- 盒子模型box-sizing
- 漸變
- 過度
- 自定義動畫
- 2D和3D
CSS屬性繼承
css三大特性 繼承(子元素繼承父元素屬性)、層疊、優(yōu)先級
CSS可以繼承的屬性
- 文字:font
- 文本:line-height
- 元素可見性:visibility: hidden
- 列表屬性: list-style
預(yù)處理器
css的預(yù)處理器增加了函數(shù)、變量等,便于維護(hù)
- SASS
- LESS
例:
<div id="app">
<span></span>
</div>
#app{
span{
// 這里寫span的樣式
}
}
@global: #eee; // 定義全局變量,利于維護(hù)使用
#app{
color: @global;
}
Node.js
入門
數(shù)據(jù)庫連接,登錄小案例
<form action="http://localhost:8080" method="post">
<input type="text" class="username" name="username" />
<input type="password" class="password" name="password"/>
<input type="submit" value="提交" />
</form>
const mysql = require('mysql')
const http = require('http')
const queryString = require('querystring')
const server = http.createServer((req, res)=>{
let postVal = "";
req.on("data", (chunk)=>{
postVal+=chunk;
})
req.on('end', ()=>{
let formVal = queryString.parse(postVal)
let username = formVal.username;
let pwd = formVal.password;
console.log(username, pwd)
// 連接數(shù)據(jù)庫
const conn = mysql.createConnection({
host: 'localhost',
port: 3306,
user: 'root',
password: '116054',
database: 'test'
})
conn.connect();
conn.query('select * from user where username=? and password=?', [username, pwd], (err, result, fields)=>{
if(err) throw err;
console.log(result);
if(result.length>0){
res.writeHead(200, {'Content-Type': 'text/html;charset=utf8'});
res.write('登錄成功')
res.end(); // 關(guān)閉http連接
}
});
conn.end(); // 關(guān)閉數(shù)據(jù)庫連接
})
})
server.listen(8080) // 端口監(jiān)聽
express
處理404
// catch 404 and forward to error handler
// 方法一
var createError = require('http-errors');
app.use(function(req, res, next) {
next(createError(404));
});
// 方法二
// 所有路由之后配置處理404
app.use((req, res, next)=>{
console.log('錯誤', err)
res.status(404).send('404 Not Found')
})
Java
面向?qū)ο蠛兔嫦蜻^程
面向過程:更注重任務(wù)順序(簡單高效)
面向?qū)ο螅焊⒅貐⑴c者(易于維護(hù)、拓展)
封裝、繼承、多態(tài)
-
封裝:內(nèi)部細(xì)節(jié)對外部調(diào)用透明,外部調(diào)用無需修改或關(guān)心內(nèi)部實(shí)現(xiàn)
1.javabean的屬性私有,提供getset對外訪問數(shù)據(jù)
2.orm框架:不需要關(guān)心鏈接如何建立,只需要調(diào)用mybatis,調(diào)方法即可 -
繼承:繼承基類方法,進(jìn)行拓展
-
多態(tài):基于對象所屬類的不同,外部對同一個方法調(diào)用,實(shí)際執(zhí)行的邏輯不同
父類類型 變量名 = new 子類對象 變量名.方法名();
JDK、JRE、JVM
- jdk(java開發(fā)工具)
- jre(java運(yùn)行環(huán)境)
- jvm(虛擬機(jī))
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-VuzCPhs5-1690204973231)(C:\Users\11605\AppData\Roaming\Typora\typora-user-images\image-20230711192250851.png)]
==和equals
- ==對比的是棧中的值:基本數(shù)據(jù)類型的變量值,引用類型是堆內(nèi)存對象的地址
- equals: 直接對比的值:value
final的作用
- 修飾類:類不可被繼承
- 修飾方法:不可被子類覆蓋,但可以重載
- 修飾變量:一旦被賦值不可被修改
String StringBuffer StringBuilder
- String是final修飾的,每次操作都會產(chǎn)生新對象(賦值變量會創(chuàng)建一個新的內(nèi)存地址)
- string buffer和string builder都是在原對象操作
- buffer是線程安全的,builder是線程不安全的
- stringbuffer方法都是synchronized修飾的
- 性能:string builder > stringbuffer > string
- 場景:經(jīng)常改變字符串就使用后兩者,優(yōu)先使用stringbuilder,多線程使用共享變量時使用string buffer
重載和重寫的區(qū)別
-
重載:發(fā)生在同一個類中,方法名必須相同,參數(shù)類型、個數(shù)、順序不同,方法返回值和訪問修飾符可以不同
-
重寫:發(fā)生在父子類中,方法名、參數(shù)列表必須相同,返回值范圍小于父類,拋出的異常范圍小于父類;父類方法修飾符是private,子類就不能重寫該方法
public int add(int a, String b) public String add(int a, String b) // 編譯報錯
List和Set的區(qū)別
-
list: 有序,按對象進(jìn)入順序保存,可重復(fù),允許多個null對象,可遍歷,可使用get(int index)獲取元素文章來源:http://www.zghlxwxcb.cn/news/detail-601934.html
-
set: 無序,元素不可重復(fù), 最多一個null對象,只能使用iterator獲取元素文章來源地址http://www.zghlxwxcb.cn/news/detail-601934.html
List<Object> list = new ArrayList<>();
hashCode與equals
ArrayList和LinkedList區(qū)別
- Arraylsi:基于動態(tài)數(shù)組,連續(xù)內(nèi)存,下標(biāo)(隨機(jī))訪問,擴(kuò)容機(jī)制:因?yàn)閿?shù)組長度固定,超出長度存數(shù)據(jù)時需要新建數(shù)組,然后將老數(shù)組的數(shù)據(jù)拷貝到新數(shù)組
- LinkedList: 基于鏈表,存儲分散在內(nèi)存中,適合做數(shù)據(jù)插入和刪除,不適合查詢(一般不用)
到了這里,關(guān)于前端八股文的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!