日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

前端小白随手笔记

發布時間:2024/3/13 HTML 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端小白随手笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前端小白的入門筆記

關于JS和ES6的問題

1.模板字符串

模板字符串是用反雙引號來標識的**()**,可以用來當作普通字符串來使用,也可以用來嵌套變量和其他模板字符串,模板字符串里面的空格和換行是會一樣顯示在頁面上的,下面是使用方法。

let str=`helloword`let str2=`helloword 123`let str3=`abc${5+5} +123`const num1= 123const num2 = 456const result = `${num1*num2+str2}`console.log(str)//hellowordconsole.log(str2)//helloword 123console.log(str3)//abc10console.log(result)//56088helloword 123

2.擴展運算符

擴展運算符(spread)是三個點(…)。將一個數組轉為用逗號分隔的參數序列。
用法一:函數中的數組傳參(替代函數的 apply 方法 )。

// ES5 的寫法 Math.max.apply(null, [14, 3, 77])// ES6 的寫法 Math.max(...[14, 3, 77])// 等同于 Math.max(14, 3, 77);

用法二:于把一個數組添加到另一個數組當中

// ES5的 寫法 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; Array.prototype.push.apply(arr1, arr2);// ES6 的寫法 let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1.push(...arr2);

用法三:復制數組

const a1 = [1, 2]; const a2 = [...a1];

用法四:合并數組

const arr1 = ['a', 'b']; const arr2 = ['c']; const arr3 = ['d', 'e']; [...arr1, ...arr2, ...arr3](淺拷貝,如果修改了原數組的成員,會同步反映到新數組。)

用法五:擴展運算符還可以將字符串轉為真正的數組。

[...'hello'] // [ "h", "e", "l", "l", "o" ]

注意,只有函數調用時,擴展運算符才可以放在圓括號中,否則會報錯。

3.解構賦值

用法一:從函數返回多個值
函數只能返回一個值,如果要返回多個值,只能將它們放在數組或對象里返回。有了解構賦值,取出這些值就非常方便。

// 返回一個數組function example() {return [1, 2, 3]; } let [a, b, c] = example(); console.log([a,b,c]) //[1, 2, 3]// 返回一個對象function example2() {return {foo: 1,bar: 2}; } let { foo, bar } = example2(); console.log({foo,bar})//{foo: 1, bar: 2} 注意接受的變量名和對象的key應該保持一致

用法二:函數參數的默認值

function example(a={aaa:'ccc'},b=2){console.log(a,b)}example()//{aaa: "ccc"} 2example(a=3)//3 2

4.for…of 循環

ES6 借鑒 C++、Java、C# 和 Python 語言,引入了for...of循環,作為遍歷所有數據結構的統一的方法。

一個數據結構只要部署了Symbol.iterator屬性,就被視為具有 iterator 接口,就可以用for…of循環遍歷它的成員。也就是說,for…of循環內部調用的是數據結構的Symbol.iterator方法。

for…of循環可以使用的范圍包括數組、Set 和 Map 結構、某些類似數組的對象(比如arguments對象、DOM NodeList 對象)、后文的 Generator 對象,以及字符串。(目前JS的數據集合有四種:數據,對象,Map,Set)
for…of循環可以代替數組實例的forEach方法。

const arr = ['red', 'green', 'blue'];arr.forEach(function (element, index) {console.log(element); // red green blueconsole.log(index); // 0 1 2 });const arr = ['red', 'green', 'blue'];for(let v of arr) {console.log(v); // red green blue }

JavaScript 原有的for…in循環,只能獲得對象的鍵名,不能直接獲取鍵值。ES6 提供for…of循環,允許遍歷獲得鍵值。

var arr = ['a', 'b', 'c', 'd'];for (let a in arr) {console.log(a); // 0 1 2 3 } //for in 不支持的對象 for (let a of arr) {console.log(a); // a b c d }

Set 和 Map 結構
Set 和 Map 結構也原生具有 Iterator 接口,可以直接使用for…of循環。

var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]); for (var e of engines) {console.log(e); } // Gecko // Trident // Webkitvar es6 = new Map(); es6.set("edition", 6); es6.set("committee", "TC39"); es6.set("standard", "ECMA-262"); for (var [name, value] of es6) {console.log(name + ": " + value); } // edition: 6 // committee: TC39 // standard: ECMA-262

上面代碼演示了如何遍歷 Set 結構和 Map 結構。值得注意的地方有兩個,首先,遍歷的順序是按照各個成員被添加進數據結構的順序。其次,Set 結構遍歷時,返回的是一個值,而 Map 結構遍歷時,返回的是一個數組,該數組的兩個成員分別為當前 Map 成員的鍵名和鍵值。

forEach 和 map 的區別:map方法返回的是一個新數組
另外:利用 filter方法進行數組的去重

const arr1 = [10,10,30,40,10,20,60,40,10] const arr2 = arr1.filter( (element, index, self) => {return self.indexOf(element)===index });console.log( arr2 );// [10, 30, 40, 20, 60]

5.async和await(處理異步的問題)

在ES6以前,我們進行異步處理都是通過回調函數的方式進行,但這種方式會有回調深淵的問題出現。其中異步處理包括:一個請求接口的函數并且返回一個值,下一個語句要用到這個值,這個時候往往函數還沒有執行完畢,就要調用這個返回值。現在我們可以用兩種方法來處理這種問題

原問題: const boo = apiCustomerCheck(pars).then(res => {return res.data.data})if (boo) {this.error_msg = ''this.error_msg = '該用戶名稱已經存在'return false}//執行 if 語句的時候,上面的接口函數還沒有執行完畢。 解決辦法: 方法一:把 if 語句放在接口函數內(不是每次情況都合適) apiCustomerCheck(pars).then(res => {const boo = res.data.dataif (boo) {this.error_msg = ''this.error_msg = '該用戶名稱已經存在'return false} 方法二:asyncawaitasync save (formName) {// 驗證手機號是否唯一const phonePar = {agencyId: JSON.parse(localStorage.entityInfo).agency_id,mobilePhone: this.ruleForm.phone}const phonePass = await checkmobilePhoneUnique(phonePar.agencyId, phonePar.mobilePhone).then(res => {return res.data.data.flag})//注意 async 和 await 要成對出現,沒有 await 的情況下執行 async 函數,//它會立即執行,返回一個 Promise 對象,并且,絕不會阻塞后面的語句。這和普通返回 Promise 對象的函數并無二致。//await 應該在async 對應的函數體內,不能在async 對應的函數里的嵌套函數。

順序問題:
//async await 的異步操作

async function helloword(){console.log(1)await waiting ()console.log(3) } function waiting(){console.log(2) } setTimeout(function () {console.log(4); },0); function saysometing(){console.log(5) }helloword() saysometing() console.log(6)

代碼從setTimeout開始,遇到setTimeout直接丟到等待隊列的最末端(其實是另一個優先級較低的等待隊列的隊首,姑且認為是promise等待隊列的最末端)。,然后到helloword() ,首先打印 1 ,遇到 await waiting (),輸出2,在執行過后馬上將后面的代碼(console.log(3))全部放到promise等待隊列中。再執行同步代碼中的saysomething()和console.log(6).
接下來執行異步代碼
首先執行await后面的代碼(console.log(3)),再執行settimeout().
記住,await 跟著settimeout函數會放到異步中,甚至是等待隊列的最后。

6.Object對象方法

(1). Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它將返回目標對象。

const target = { a: 1, d: 2 }; const source = { b: 4, c: 5 };const returnedTarget = Object.assign(target, source);console.log(target); // expected output: Object { a: 1, b: 4, c: 5 ,d: 2}console.log(returnedTarget); // expected output: Object { a: 1, b: 4, c: 5 ,d: 2}

如果目標對象中的屬性具有相同的鍵,則屬性將被源對象中的屬性覆蓋。后面的源對象的屬性將類似地覆蓋前面的源對象的屬性。

Object.assign 方法只會拷貝源對象自身的并且可枚舉的屬性到目標對象。該方法使用源對象的[[Get]]和目標對象的[[Set]],所以它會調用相關 getter 和 setter。因此,它分配屬性,而不僅僅是復制或定義新的屬性。如果合并源包含getter,這可能使其不適合將新屬性合并到原型中。為了將屬性定義(包括其可枚舉性)復制到原型,應使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。

String類型和 Symbol 類型的屬性都會被拷貝。

在出現錯誤的情況下,例如,如果屬性不可寫,會引發TypeError,如果在引發錯誤之前添加了任何屬性,則可以更改target對象。

注意,Object.assign 不會在那些source對象值為 null 或 undefined 的時候拋出錯誤。

const o1 = { a: 1 }; const o2 = { b: 2 }; const o3 = { c: 3 };const obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目標對象自身也會改變。

(2). Object.definePropety() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 并返回這個對象。

Object.defineProperty(obj, prop, descriptor)
參數:

obj
要在其上定義屬性的對象。
prop
要定義或修改的屬性的名稱。
descriptor
將被定義或修改的屬性描述符。

該方法允許精確添加或修改對象的屬性。通過賦值操作添加的普通屬性是可枚舉的,能夠在屬性枚舉期間呈現出來(for…in 或
Object.keys 方法), 這些屬性的值可以被改變,也可以被刪除。這個方法允許修改默認的額外選項(或配置)。默認情況下,使用
Object.defineProperty() 添加的屬性值是不可修改的。

var o = {}; // 創建一個新對象// 在對象中添加一個屬性與數據描述符的示例 Object.defineProperty(o, "a", {value : 37,writable : true,enumerable : true,configurable : true });// 對象o擁有了屬性a,值為37// 在對象中添加一個屬性與存取描述符的示例 var bValue; Object.defineProperty(o, "b", {get : function(){return bValue;},set : function(newValue){bValue = newValue;},enumerable : true,configurable : true });o.b = 38; // 對象o擁有了屬性b,值為38// o.b的值現在總是與bValue相同,除非重新定義o.b// 數據描述符和存取描述符不能混合使用 Object.defineProperty(o, "conflict", {value: 0x9f91102, get: function() { return 0xdeadbeef; } }); // throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors

考慮特性被賦予的默認特性值非常重要,通常,使用點運算符和Object.defineProperty()為對象的屬性賦值時,數據描述符中的屬性默認值是不同的,如下例所示。

var o = {};o.a = 1; // 等同于 : Object.defineProperty(o, "a", {value : 1,writable : true,configurable : true,enumerable : true });// 另一方面, Object.defineProperty(o, "a", { value : 1 }); // 等同于 : Object.defineProperty(o, "a", {value : 1,writable : false,configurable : false,enumerable : false });

7.原型鏈

每個對象擁有一個原型對象,通過 proto 指針指向上一個原型 ,并從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null,這種關系被稱為原型鏈(prototype chain)。

根據規范不建議直接使用 proto,推薦使用 Object.getPrototypeOf(),不過為了行文方便邏輯清晰,下面都以 proto 代替。

注意上面的說法,原型上的方法和屬性被 繼承 到新對象中,并不是被復制到新對象。

prototype 和 proto

其中原型對象 prototype 是構造函數的屬性,proto 是每個實例上都有的屬性,這兩個并不一樣,但 foo.proto 和 Foo.prototype 指向同一個對象。
原型鏈的構建依賴于 proto,如上圖通過 foo.proto 指向 Foo.prototype,foo.proto.proto 指向 Bichon.prototype,如此一層一層最終鏈接到 null。

實現instanceof

function instance_of(L,R){let Y = R.prototypelet Z = L.__proto__if(Z===null)return falseif(Z===Y)return trueZ = Z.__proto__} function C(){} function D(){} var o = new C();console.log(instance_of(o, C))
總結

每個對象擁有一個原型對象,通過 proto 指針指向上一個原型 ,并從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null,這種關系被稱為**原型鏈 **

當訪問一個對象的屬性 / 方法時,它不僅僅在該對象上查找,還會查找該對象的原型,以及該對象的原型的原型,一層一層向上查找,直到找到一個名字匹配的屬性 / 方法或到達原型鏈的末尾(null)。

原型鏈的構建依賴于 proto,一層一層最終鏈接到 null。

tnstanceof 原理就是一層一層查找 proto,如果和 constructor.prototype 相等則返回 true,如果一直沒有查找成功則返回 false。

原型鏈繼承的本質是重寫原型對象,代之以一個新類型的實例。

8.call 和 apply 的用法

call() 方法調用一個函數, 其具有一個指定的 this 值和分別地提供的參數(參數的列表)。

call() 和 apply()的區別在于,call()方法接受的是若干個參數的列表,而apply()方法接受的是一個包含多個參數的數組。

作用一 合并數組

let arr1 = ['Mike','John','Amry','jack'] let arr2 = ['jay','lucy'] Array.prototype.push.apply(arr1,arr2) console.log(arr1) //["Mike", "John", "Amry", "jack", "jay", "lucy"]

作用二 找出數組中的最大值

let arr = [100,200,300] console.log(Math.max.apply(Math,arr))//300 console.log(Math.max.call(Math,...arr))//300 為什么要這么用呢,因為數組 numbers 本身沒有 max 方法,但是 Math 有呀, 所以這里就是借助 call / apply 使用 Math.max 方法。

9.關于前端跨域的問題

(1)什么是跨域:

1、以下三種情況出現一種都屬于跨域:協議不同、域名不同、端口號不同
2、跨域這個概念來自一個叫 “同源策略” 的東西。同源策略是瀏覽器(注意是瀏覽器,跟通信協議無關)上為了安全考慮實施的非常重要的安全機制。
3、Ajax 默認只能獲取到同源的數據,對于非同源的數據,Ajax是獲取不到的。

(2)解決跨域的辦法有哪些

1、解決跨域的方法簡單的有三種:反向代理,JSONP,CORS。
2、如果訪問的別人服務器的資源,并且未設置JSONP,服務器也沒有設置CORS接口,那么唯一的選擇就是使用自己的服務器進行反向代理。
3、反向代理:就是使用自己的服務器,在后端請求目標服務器的數據,然后返回給客戶端。反向代理服務器,最常用的就是Nginx。
但是作為前端代碼實現的Node.js也可以搭建反向代理服務器。
比如我有一個后端接口:http://39.105.136.190:3000/zhuiszhu/goods/getList,可以獲取一些商品列表數據,但是我運行的node項目是在 localhost:3000 下的,明顯構成跨域。
我們根據項目使用的框架不同,處理的方式也不同。
我們經常在vue開發項目的時候,會用webpack作為前端自動化構建工具的話,也會使用到webpack-dev-server的插件,那么可以引用webpack-dev-server來進行配置跨域方案。
webpack-dev-server是一個小型的nodejs服務器,是基于express框架的,用于實時監聽和打包編譯靜態資源。其中里面有一個屬性是proxy,是專門來配置代理請求接口的。
你只需要在webpack.config.js中 devServer中如下設置即可:
devServer: {
port: 3000,
inline: true,
proxy: {
“/zhuiszhu”: {
target: “http://39.105.136.190:3000/”,
changeOrigin: true //必須配置為true,才能正確代理
}
}
},
4、JSONP
JSONP基本思想是,網頁通過添加一個“<s c r i p t刪除線格式 >”元素,向服務器請求JSON數
據,這種做法不受同源政策限制;服務器收到請求后,將數據作為參數放在一個指定名字的回調函數里傳回來,這個回調函數的名字我們需要通過js定義好。
比如:當頁面資源加載完畢時候,獲取跨域的數據,并且制定回調函數的名字為為foo:
window.onload = function () {
var script = document.createElement(“script”);
script.setAttribute(“type”,“text/javascript”);
script.src = "http://bbb.com?callback=foo;
document.body.appendChild(script);
};
foo(data) {
console.log(data); // data即為跨域獲取到的數據
}
使用JSONP需要注意:
必須后端配置相應回調函數。
只能發送GET請求。
5、CORS全稱“ Cross-origin resource sharing ”(跨域資源共享),相比JSONP, CORS允許任何類型的請求 。
CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信

10.關于 js 中 this 指向的問題

1、 主要分為兩類,分別是顯式綁定和隱式綁定。
2、現實是綁定的主要包括 apply、call、bind等方法。
3、這里主要討論的是隱式綁定。
4、主要是以下隱式綁定的場景討論:
全局上下文
直接調用函數
對象.方法的形式調用
DOM事件綁定(特殊)
new構造函數綁定
箭頭函數

  • 全局上下文
    全局上下文默認this指向window, 嚴格模式下指向undefined。
  • 直接調用函數
    比如:
  • let obj = {a: function() {console.log(this);} } let func = obj.a; func(); //這里的打印結果還是 window ,應該是看函數在什么地方被調用。
  • 對象.方法的形式調用
    還是剛剛的例子,我如果這樣寫:
  • obj.a(); //這就是對象.方法的情況,this指向這個對象
  • new+構造函數
    此時構造函數中的this指向實例對象。
  • 箭頭函數?
    箭頭函數沒有this, 因此也不能綁定。里面的this會指向當前最近的非箭頭函數的this,找不到就是window(嚴格模式是undefined)。比如:
  • let obj = {a: function() {let do = () => {console.log(this);}do();} } obj.a(); // 找到最近的非箭頭函數a,a現在綁定著obj, 因此箭頭函數中的this是obj

    優先級: new > call、apply、bind > 對象.方法 > 直接調用。

    11.關于 js 中 深拷貝和淺拷貝的問題

    首先 先明白什么是拷貝:

    let arr = [1, 2, 3]; let newArr = arr; newArr[0] = 100;console.log(arr);//[100, 2, 3]

    這是直接賦值的情況,不涉及任何拷貝。當改變newArr的時候,由于是同一個引用,arr指向的值也跟著改變。
    現在進行淺拷貝:

    let arr = [1, 2, 3]; let newArr = arr.slice(); newArr[0] = 100;console.log(arr);//[1, 2, 3]

    當修改newArr的時候,arr的值并不改變。什么原因?因為這里newArr是arr淺拷貝后的結果,newArr和arr現在引用的已經不是同一塊空間啦!
    這就是淺拷貝。
    但是這又會帶來一個潛在的問題:

    let arr = [1, 2, {val: 4}]; let newArr = arr.slice(); newArr[2].val = 1000;console.log(arr);//[ 1, 2, { val: 1000 } ]

    咦!不是已經不是同一塊空間的引用了嗎?為什么改變了newArr改變了第二個元素的val值,arr也跟著變了。
    這就是淺拷貝的限制所在了。它只能拷貝一層對象。如果有對象的嵌套,那么淺拷貝將無能為力。但幸運的是,深拷貝就是為了解決這個問題而生的,它能
    解決無限極的對象嵌套問題,實現徹底的拷貝。
    下面一起看看實現淺拷貝的幾種方式:

    Object.assign()
    但是需要注意的是,Object.assgin() 拷貝的是對象的屬性的引用,而不是對象本身。

    let obj = { name: 'sy', age: 18 }; const obj2 = Object.assign({}, obj, {name: 'sss'}); console.log(obj2);//{ name: 'sss', age: 18 }

    concat 淺拷貝數組

    let arr = [1, 2, 3]; let newArr = arr.concat(); newArr[1] = 100; console.log(arr);//[ 1, 2, 3 ]

    slice淺拷貝

    let arr = [1, 2, 3]; let newArr = arr.slice(); newArr[0] = 100;console.log(arr);//[1, 2, 3]

    …展開運算符

    let arr = [1, 2, 3]; let newArr = [...arr];//跟arr.slice()是一樣的效果

    關于vue的問題

    1.父子組件的傳值方式

    (1).父組件向子組件傳值

    父組件: <template><div><input v-model="name"/><child :sendmsg="name"></child></div> </template> <script> import child from "./child"; export default {components: {child},data () {return {name:''}} } </script><style scoped> </style> 子組件: <template><div><span>{{sendmsg}}</span></div> </template> <script> export default {props:{sendmsg:String,require:true}} </script><style scoped> </style>

    (2).子組件向父組件傳值

    子組件: <template><div><span>{{msg}}</span><input type="button" value="點擊我向父組件傳值" @click="sendmsg"></div> </template> <script> export default {data () {return {msg:'Helloword'}},methods: {sendmsg(){this.$emit('func',this.msg)}} } </script><style scoped> </style> 父組件: <template><div><span>{{msg}}</span><child @func="getmsgfromchild"></child></div> </template> <script> import child from "./child" export default {components: {child},data () {return {}},methods: {getmsgfromchild(data){this.msg=data}} } </script><style scoped> </style>

    (3)vue中ref的作用

    ref 被用來給元素或子組件注冊引用信息。引用信息將會注冊在父組件的 $refs 對象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例
    在普通的 DOM 元素上使用,引用指向的就是 DOM 元素

    (4).vuex 狀態管理

    Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化

    Vuex 解決了多個視圖依賴于同一狀態和來自不同視圖的行為需要變更同一狀態的問題,將開發者的精力聚焦于數據的更新而不是數據在組件之間的傳遞上。

    4.1 Vuex各個模塊

    (1)state:用于數據的存儲,是store中的唯一數據源

    // 定義 new Vuex.Store({state: {allProducts: []}//... }) // 組件中獲取 this.$store.state.allProducts

    (2)getters:如vue中的計算屬性一樣,基于state數據的二次包裝,常用于數據的篩選和多個數據的相關性計算。

    // 定義 getters: {cartProducts(state, getters, rootState) => (getters.allProducts.filter(p => p.quantity)) } // 組件中獲取 this.$store.getters.cartProducts

    (3)mutations:類似函數,改變state數據的唯一途徑,且不能用于處理異步事件(重點!!!)

    // 定義 mutations: {setProducts (state, products) {state.allProducts = products} }// 組件中使用 this.$store.commit('setProducts', {//..options})

    (4)actions:類似于mutation,用于提交mutation來改變狀態,而不直接變更狀態,可以包含任意異步操作

    // 定義(shop為api) actions: {getAllProducts ({ commit }, payload) {shop.getProducts((res) => {commit('setProducts', res)})} }// 組件中使用 this.$store.dispatch('getAllProducts', {//..payload})

    (5)modules:類似于命名空間,用于項目中將各個模塊的狀態分開定義和操作,便于維護

    // 定義 const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... } }const moduleB = {state: { ... },mutations: { ... },actions: { ... } }const store = new Vuex.Store({modules: {a: moduleA,b: moduleB} })// 組件中使用 store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態
    4.2 輔助函數

    在組件中使用store中的數據或方法時,按照上面的說法,每次都要this.$store.的方式去獲取,有沒有簡單一點的方式呢?輔助函數就是為了解決這個問題

    // 組件中注冊 import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'export default {computed: {// 數組形式,當映射的計算屬性的名稱與 state 的子節點名稱相同時使用...mapState(['allProducts'])// 對象形式,可重命名 state 子節點名稱...mapState({products: state => state.allProducts})// 下面為了簡便,均以數組形式使用...mapGetters(['cartProducts'])},methods: {...mapMutations(['setProducts']),...mapActions(['getAllProducts'])} }// 組件中使用 // 變量 this.allProducts this.products // 方法 this.setProducts() this.getAllProducts()

    附件:store 結構使用如下方式

    store├── index.js # 導出 store 的地方├── state.js # 根級別的 state├── getters.js # 二次包裝state數據├── actions.js # 根級別的 action├── mutations.js # 根級別的 mutation├── mutation-types.js # 所有 mutation 的常量映射表└── modules # 如果有.├── ...
    4.3 vuex 安裝

    (1)在項目中安裝Vuex:

    npm install vuex --save

    (2)在src目錄下新建store/index.js,其中代碼如下:

    import Vue from 'vue' import Vuex from 'vuex' // 修改state時在console打印,便于調試 import createLogger from 'vuex/dist/logger'Vue.use(Vuex)const debug = process.env.NODE_ENV !== 'production'const state = {} const getters = {} const mutataions = {} const actions = {}export default new Vuex.Store({state,getters,mutataions,actions,// 嚴格模式,非法修改state時報錯strict: debug,plugins: debug ? [createLogger()] : [] })

    (3)在入口文件main.js中添加:

    // ... import router from './router' import store from './store'new Vue({el: '#app',router,store,// ... })

    可以對比vue-router和vuex的安裝方式:它們均為vue插件,并在實例化組件時引入,在該實例下的所有組件均可由this. r o u t e r 和 t h i s . router和this. routerthis.store的方式查詢到對應的插件實例

    2.路由跳轉的方式

  • router-link
  • 不帶參數
  • <router-link :to="{name:'home'}"> <router-link :to="{path:'/home'}"> //name,path都行, 建議用name // 注意:router-link中鏈接如果是'/'開始就是從根路由開始,如果開始不帶'/',則從當前路由開始。

    2.帶參數

    <router-link :to="{name:'home', params: {id:1}}"> // params傳參數 (類似post) // 路由配置 path: "/home/:id" 或者 path: "/home:id" // 不配置path ,第一次可請求,刷新頁面id會消失 // 配置path,刷新頁面id會保留// html 取參 $route.params.id // script 取參 this.$route.params.id<router-link :to="{name:'home', query: {id:1}}"> // query傳參數 (類似get,url后面會顯示參數) // 路由可不配置// html 取參 $route.query.id // script 取參 this.$route.query.id
  • this.$router.push() (函數里面調用)
  • 不帶參數
  • this.$router.push('/home') this.$router.push({name:'home'}) this.$router.push({path:'/home'})
  • query傳參
  • this.$router.push({name:'home',query: {id:'1'}}) this.$router.push({path:'/home',query: {id:'1'}})// html 取參 $route.query.id // script 取參 this.$route.query.id
  • params傳參
  • this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name// 路由配置 path: "/home/:id" 或者 path: "/home:id" , // 不配置path ,第一次可請求,刷新頁面id會消失 // 配置path,刷新頁面id會保留// html 取參 $route.params.id // script 取參 this.$route.params.id
  • query和params區別
    query類似 get, 跳轉之后頁面 url后面會拼接參數,類似?id=1, 非重要性的可以這樣傳, 密碼之類還是用params刷新頁面id還在
  • params類似 post, 跳轉之后頁面 url后面不會拼接參數 , 但是刷新頁面id 會消失

  • this.$router.replace() (用法同上,push)
  • this. r o u t e r . g o ( n ) ( ) t h i s . router.go(n) () this. router.go(n)()this.router.go(n)
    向前或者向后跳轉n個頁面,n可為正整數或負整數
    ps : 區別
  • this. r o u t e r . p u s h 跳 轉 到 指 定 u r l 路 徑 , 并 想 h i s t o r y 棧 中 添 加 一 個 記 錄 , 點 擊 后 退 會 返 回 到 上 一 個 頁 面 t h i s . router.push 跳轉到指定url路徑,并想history棧中添加一個記錄,點擊后退會返回到上一個頁面 this. router.pushurlhistory退this.router.replace
    跳轉到指定url路徑,但是history棧中不會有記錄,點擊返回會跳轉到上上個頁面 (就是直接替換了當前頁面)

    this.$router.go(n)
    向前或者向后跳轉n個頁面,n可為正整數或負整數

    3.Element UI庫的問題

    (1)向在dialog彈窗中設置高度,避免內容過多時,彈窗高度太大

    <style lang='scss'> .el-dialog__body{height: calc(70vh - 100px);overflow: auto;} </style>

    注意這個沒有加上 scoped 所以要在前面加個div的類名或者id來控制避免全局污染

    (2)Element UI中 組件的回車事件要加上.native修飾符

    <el-button icon="el-icon-plus" @keyup.enter.native="pressEnter()">添加 </el-button>

    (3)Element UI中 table組件

    在 table 組件中設置了 height 或者 max-height min-height之后,會固定表頭,其中height設置auto,表身高度隨著內容的變化而變化。

    <el-table:data="orderList"stripemax-height="200px"style="width: 100%;">

    (4)按需引入 Element UI庫

    1、借助 babel-plugin-component,我們可以只引入需要的組件,以達到減小項目體積的目的:

    npm install babel-plugin-component -D

    2、更改.babelrc文件

    "plugins": [["component",{"libraryName": "element-ui","styleLibraryName": "theme-chalk"}]]

    3、在 main.js 中引入需要的組件

    import { Select, Option, OptionGroup, Input, Tree, Dialog, Row, Col } from 'element-ui' Vue.use(Select)

    (5)iview 組件中表格本身的單擊事件和表格中某個按鈕的點擊事件一起觸發的問題:

    解決方法: 我們只需要在按鈕的點擊事件中加上一行就可以解決這個問題

    delectTableData(nowid) {event.stopPropagation();this.$Modal.confirm({title: "刪除提示",content: "<p>確定要刪除嗎?</p>",// 確定刪除onOk :async () => {const { data: res } = await this.$http.delete("xxxx" + id);if (res.code !== 200) {return this.$Message.error("刪除失敗");} else {this.$Message.success("刪除成功");}}});},

    在刪除按鈕事件里面添加event.stopPropagation();,來阻止事件冒泡就可以解決了。

    4.vue.js中報錯: TypeError: Cannot read property ‘indexOf’ of undefined

    問題分析:1、可能是變量名寫錯,導致未定義報錯
    2、可能是異步的問題,需要用到 async 和 await 去解決
    3、最后是網速慢的問題,導致變量未返回,這時候需要結合 watch 和 if(indexOf !== undifined){} ,來進行解決。

    5.vue中樣式的用法

    (1)在標簽中寫入 :style=" “, 如果” “里面的是一個字符串,假如這個字符串是sty_color,sty_color應該寫在data上,并且是一個對象;如果” "里面的是一個對象,那么這個對象的值應該是data上的value。

    (2)在標簽中寫入 :class=" “,” "里面的是一個對象,對象的鍵是一個類,寫在style標簽中;對象的值是一個布爾值,用來決定這個類是否應用,這個值可以寫在data上面。

    <style>.red{color:cornflowerblue}</style> <body><div id="app"><!-- 對象就是無序鍵值對的集合 --><h1 :style="{color:bluecolor}">這是一個和h1</h1><h1 :style="styleobj1">這是2個和h1</h1><h1 :class="{'red':flag===true}">這是第三個h1</h1></div><script>var vm = new Vue({el: '#app',data: { styleobj1: { color: 'red', 'font-weight': 800},styleobj2: {'font-style': 'italic'} ,bluecolor:'blue',flag:true},methods: {}});

    6.vue-cli配置項目接口地址

    使用 Vue-cli 創建的項目,開發地址是 localhost:8080,需要訪問非本機上的接口http://10.1.0.34:8000/queryRole。不同域名之間的訪問,需要跨域才能正確請求。跨域的方法很多,通常都需要后臺配置,不過 Vue-cli 創建的項目,可以直接利用 Node.js 代理服務器,通過修改vue proxyTable接口實現跨域請求。在vue-cli項目中的config文件夾下的index.js配置文件中。
    修改前的dev:

    dev: { env: require('./dev.env'), port: 8080, autoOpenBrowser: true, assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: {}, cssSourceMap: false }

    只要修改里面的proxyTable: {}項:

    proxyTable: { '/api': { //代理地址 target: 'http://10.1.0.34:8000/', //需要代理的地址 changeOrigin: true, //是否跨域 secure: false, pathRewrite: { '^/api': '/' //本身的接口地址沒有 '/api' 這種通用前綴,所以要rewrite,如果本身有則去掉 }} }

    7.vue中的兄弟組件之間的通信

    可以直接在項目中的 main.js 初始化 EventBus :

    // main.js Vue.prototype.$EventBus = new Vue() <template><button @click="increment()">+</button> </template><script> import { EventBus } from "../event-bus.js";export default {name: "IncrementCount",data() {return {num: 1,deg:180};},methods: {increment() {EventBus.$emit("incremented", {num:this.num,deg:this.deg});}}};</script> //在兄弟組件接收值mounted() {EventBus.$on("incremented", ({num,deg}) => {this.fontCount += numthis.$nextTick(()=>{this.backCount += numthis.degValue += deg;})});EventBus.$on("decreased", ({num,deg}) => {this.fontCount -= numthis.$nextTick(()=>{this.backCount -= numthis.degValue -= deg;})});}

    現在我們已經創建了 EventBus ,接下來你需要做到的就是在你的組件中加載它,并且調用同一個方法,就如你在父子組件中互相傳遞消息一樣。

    8.關于 vue 的其他使用:

    1、在默認情況下,父組件向子組件傳值,假如子組件修改父組件傳過來的值,會產生報錯。那如何對 prop 進行雙向綁定,Vue提供了sync修飾符(即通過 this.emit(‘update:要更新的父傳過來的數據’, 更新后的數據, 父組件的要加上修飾符.sync)更新父組件的值,),舉個例子:

    <!--html代碼--> <div id="app"><span>{{title}}</span><text-document v-bind:title.sync="title"></text-document> </div> Vue.component('text-document', {props: ['title'],template: `<button @click="change">change</button>`,methods: {change () {this.$emit('update:title', 'change')}}, }) new Vue({el: '#app',data() {return {title: 'default'}} })

    2、關于爺爺組件和孫子組件通信的問題
    首先這兩個組件通信的方法有很多,如 vuex、eventBus、通過兒子組件向上向下傳遞等等,現在介紹的是一種比較簡便的方法:$attrs 和 $listeners。(詳細介紹看https://www.jianshu.com/p/ce8ca875c337)

    <template><div style="padding:50px;"><childcom :name="name" :age="age" :sex="sex"></childcom> // 把要傳給子組件、孫子組件的變量寫在子組件的屬性上</div> </template> <script> export default {'name':'test',props:[],data(){return {'name':'張三','age':'30','sex':'男'}},components:{'childcom':{template:`<div><div>{{name}}</div><grandcom v-bind="$attrs"></grandcom> </div>`, // 在孫子組件的標簽上綁定 $attrs v-bind = "$attrs",這時候 attrs是一個對象,包括了 爺爺組件傳下來的變量減去 props 聲明了的(在這里就是age,sex 傳給了孫子組件)props:['name'],components: {'grandcom':{template:`<div>{{$attrs}}</div>`,} // 就是{age: 30, sex: 男}}}} } </script>

    如果現在孫子組件要改變爺爺組件的方法,(組件傳值都是單向流,子孫組件不能直接改變父組件的傳過來的值),方法有很多,這里介紹的是 $listeners

    <template><div><childcom :name="name" :age="age" :sex="sex" @testChangeName="changeName"></childcom></div> </template> <script> export default {'name':'test',props:[],data(){return {'name':'張三','age':'30','sex':'男'}},components:{'childcom':{props:['name'],template:`<div><div>我是子組件 {{name}}</div><grandcom v-bind="$attrs" v-on="$listeners"></grandcom></div>`, // 孫子組件加上監聽 $listeners (v-on="$listeners"),就可像改變父組件一樣改變爺爺組件components: {'grandcom':{template:`<div>我是孫子組件-------<button @click="grandChangeName">改變名字</button></div>`,methods:{grandChangeName(){this.$emit('testChangeName','kkkkkk')}}}}}},methods:{changeName(val){this.name = val}} } </script>

    最后講的是 inheritAttrs 屬性
    在父組件寫的子組件的屬性在設置子組件設置 inheritAttrs :true 的時候會被子組件的根元素繼承下來(有沖突的時候會選用在父組件寫的屬性),在子組件設置 inheritAttrs :false 的時候,子組件的根元素不會繼承 父組件頁面寫的 子組件標簽上的屬性。

    3、Vue的異常捕獲

    // vue的異常捕獲, 在異步請求中捕獲異常需要 catch(error => {// this.$throw(error)// })// 在 main.js 寫入異常捕獲const function errorHandler = (error, vm) => {console.error('拋出異常')console.error(vm)console.error(error) }Vue.config.errorHandler = errorHandler Vue.prototype.$throw = function(error){return errorHandler(error, this) }

    關于CSS的問題

    1.兩個 div 水平擺放,頂部對齊

    方法一:當兩個 div 設置了 inline-block 之后,兩個 div 的底部會對齊,如果想頂部對齊,就要設置兩個 div 的vertical-align: top
    方法二:只有左側div設置為 float:left ,右側div設置 overflow:auto ;,右側div將會占據整個右側剩余寬度。同樣這兩個 div 會頂部對齊 。

    2.設置首字母的大寫

    在 css2中,樣式 text-transform ,可以設置首字母大寫,全體大寫,全體小寫。他的參數有:capitalize: 文本中的每個單詞以大寫字母開頭。
    uppercase: 僅有大寫字母。
    lowercase: 無大寫字母,僅有小寫字母。

    <style>.upperCase{text-transform: capitalize}</style> </head> <body><span class="upperCase">fsdsd是個v第十九屆dvnj+vrv vnrvu </span> </body>//Fsdsd是個V第十九屆Dvnj+Vrv Vnrvu

    3.驗證表單控件

    這里的驗證表單控件僅僅操作css,還不會涉及js。操作方法用到了 HTML5 關于 的新屬性 —— pattern( 檢查控件值的正則表達式 )。下面舉個例子:

    input[type="text"]:invalid ~ input[type="submit"] {display: none }<div class="form-css"><input type="text" name="tel" placeholder="輸入手機號碼" pattern="^1[3456789]\d{9}$" required><br><input type="text" name="smscode" placeholder="輸入驗證碼" pattern="\d{4}" required><br><input type="submit" ></input> </div>

    invalid 偽類和 vaild 偽類
    valid 偽類,匹配通過 pattern 驗證的元素
    invalid 偽類,匹配未通過 pattern 驗證的元素

    4.布局問題

    (1)左右居中

    行內元素: text-align: center

    定寬塊狀元素: 左右 margin 值為 auto

    不定寬塊狀元素: table布局,position + transform

    /* 方案1 */ .wrap {text-align: center } .center {display: inline;/* or *//* display: inline-block; */ } /* 方案2 */ .center {width: 100px;margin: 0 auto; } /* 方案2 */ .wrap {position: relative; } .center {position: absulote;left: 50%;transform: translateX(-50%); }

    5.less 和 calc 存在沖突的問題

    如果直接寫

    <style lang="less">width:calc(100vw - 56px);

    會存在問題,甚至會報錯。其實他們兩者是可以兼容的
    解決方法也挺簡單,加上~用""包起來。

    .class {height: calc(~"100% - 50px"); }

    可如果要用變量怎么用呢?也不復雜,像下面這樣就搞定啦。

    .class {@cap: 50px;height: calc(~"100% - @{cap}"); }

    6.border-radius 會被內部的背景顏色覆蓋的問題

    當大 div (設置了 border-radius)的背景顏色 和內部的 div 的背景顏色不相同時,內部的 div 會覆蓋 圓角,這時候需要在大 div 中設置一個 overflow: auto, 即可解決問題。

    注意問題

    1、不能在數組的循環當中刪除數組item,這樣會導致數組的下標出錯,執行出問題。

    2、鎖定 npm 依賴包版本的問題,首先,版本號前面的標記意思:^意味著所下載的包有可能會有更高的次版本號(第二位)或者修訂版本號(第三位),而~意味著有可能會有更高的修訂版本號。

    怎么鎖定依賴包的依賴包版本的問題:使用npm shrinkwrap命令。會生成npm-shrinkwrap.json文件,和package.lock.json是一模一樣。當別的地方或者同事執行 npm i 命令的時候就會按照 npm-shrinkwrap.json文件的指定依賴包來安裝。區別是package.lock.json在發布時不會上傳到npm倉庫中.

    總結

    以上是生活随笔為你收集整理的前端小白随手笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。