系統學習前端Vue框架,筆記記錄於B站的why老師,具體視頻連接,在此感謝老師的悉心授課。個人github筆記地址javascript
歡迎訪問個人博客css
My Blog: https://coderblue.cn/
Github:https://github.com/CoderBleu
My Project:https://coderblue.cn/project/html
<script src="../js/vue.js"></script> <div id="hi">Hello {{name}}</div> <div class="movie"> <ul> <li v-for="item in movies"> {{item}} </li> </ul> </div> <script> const hi = new Vue({ el: "#hi", data: { name: 'Vue.js' } }) let movie = new Vue({ el: '.movie', data: { movies: ["星際穿越", '大話西遊', '海賊王之黃金城', '復仇者聯盟'] // 注意:能夠經過movie.movies.push('盜夢空間') } }) </script>
<body> <!-- view --> <div id="count"> <h2>{{counter}}</h2> <button v-on:click="add">+</button> <button v-on:click="sub">-</button> <!-- <button v-on:click="counter++">+</button> <button v-on:click="counter--">-</button> --> </div> <ol> <li>緣由是你的body中的div中沒有設置id,vue沒有綁定</li> <li>解決:body中加 div id="app" </li> <li>雙向綁定:view,model,ViewModel</li> </ol> </body> <script> // proxy: model const obj = { counter: 0 } // ViewModel let count = new Vue({ el: "#count", data: obj, methods: { add: function() { this.counter++; }, sub: function(){ this.counter--; } } }) </script>
MVVM簡介
MVVM 是Model-View-ViewModel 的縮寫,它是一種基於前端開發的架構模式,其核心是提供對View 和 ViewModel 的雙向數據綁定,這使得ViewModel 的狀態改變能夠自動傳遞給 View,即所謂的數據雙向綁定。
Vue.js 是一個提供了 MVVM 風格的雙向數據綁定的 Javascript 庫,專一於View 層。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel負責鏈接 View 和 Model,保證視圖和數據的一致性,這種輕量級的架構讓前端開發更加高效、便捷。前端
MVVM模型
vue
MVVM拆開來即爲Model-View-ViewModel,有View,ViewModel,Model三部分組成。java
Vue.js中mvvm的體現
Vue.js的實現方式,對數據(Model)進行劫持,當數據變更時,數據會出發劫持時綁定的方法,對視圖進行更新。
node
實例分析以下:
react
Vue.js關於雙向數據綁定的一些實現細節webpack
vue是採用Object.defineProperty的getter和setter,並結合觀察者模式來實現數據綁定的。當把一個普通的javascript對象傳給Vue實例來做爲它的data選項時,Vue將遍歷它的屬性,用Object.defineProperty將它們轉爲getter/setter。用戶看不到getter/setter,可是在內部它們讓Vue追蹤依賴。在屬性被訪問和修改時通知變化。
git
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="../js/vue.js"></script> <style> [v-cloak] { display: none !important; } </style> </head> <body> <div id="app"> <!-- 讓未被編譯的從新編譯加載 Vue加入了延緩響應的指令v-cloak,在與css:[v-cloak] { display: none } 的配合下, 能夠隱藏未編譯 Mustache 的標籤直到實例準備完畢,v-cloak屬性纔會被自動去除,對應的標籤也纔可見了 --> <h4 >Hello {{count}}</h4> </div> <script> setTimeout(() => { let app = new Vue({ el: '#app', data: { count: 'v-cloak' }, methods: { }, beforeMount () { alert("有趣"); } }); }, 1000); </script> </body> </html>
傳給 v-bind:class
一個對象,以動態地切換 class(語法糖:’:表示’)
根據isActive的true,false變化,動態綁定單個class
<div :class="{ active: isActive==true }"></div>
計算屬性的方式綁定class
<div :class="classObject"></div> data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, //isActive爲true,且error不爲null 'text-danger': this.error && this.error.type === 'fatal' //error爲null且this.error.type === 'fatal' } } }
數組的方式綁定class
<div v-bind:class="[activeClass, errorClass]"></div> data: { activeClass: 'active', errorClass: 'text-danger' } 渲染爲: <div class="active text-danger"></div>
三元表達式動態切換class(推薦)
<div :class="[isActive ? activeClass : '', errorClass]"></div>
v-bind:style 的對象語法十分直觀——看着很是像 CSS,但實際上是一個 JavaScript 對象。CSS 屬性名能夠用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> data: { activeColor: 'red', fontSize: 30 }
直接綁定到一個樣式對象一般更好,這會讓模板更清晰:
<div :style="styleObject"></div> data: { styleObject: { color: 'red', fontSize: '13px' } }
v-bind:style 的數組語法能夠將多個樣式對象應用到同一個元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
<body> <div id="app"> <h3> {{fullName}}</h3> </div> <script> let app = new Vue({ el: '#app', data: { fisrtName: 'Lom', lastName: 'Name' }, computed: { // fullName: function(){ // return this.fisrtName + ' ' + this.lastName; // } // fullName: { // get: function () { // return this.fisrtName + ' ' + this.lastName; // } // } // 底層方法 fullName: { set: function (newValue) { console.log("---------", newValue); //split() 方法用於把一個字符串分割成字符串數組。 const value = newValue.split(' '); this.fisrtName = value[0]; this.lastName = value[1]; }, get: function () { return this.fisrtName + ' ' + this.lastName; } } } }); </script> </body>
<body> <div id="app"> <!-- 1. 經過字符串直接拼接,不美觀 --> <h3> {{fisrtName}} {{lastName}}</h3> <!-- 2. 經過方法:調用方法一次就從新執行一次 --> <h3> {{getFullName()}}</h3> <!-- 3. 經過計算屬性:執行一次後,會將此緩存起來,後面在調用會直接有結果顯示,不會頻繁調用 --> <h3> {{fullName}}</h3> </div> <script> const app = new Vue({ el: '#app', data: { fisrtName: 'Lom', lastName: 'Name' }, methods: { getFullName: function(){ console.log("fullName"); return this.fisrtName + ' ' + this.lastName; } }, computed: { fullName: { get: function () { console.log("fullName"); return this.fisrtName + ' ' + this.lastName; } } } }); </script> </body>
<body> <div id="app"> <h3>{{counter}}</h3> <!-- v-on語法糖使用:@ --> <button @click="increment">+</button> <!-- 不須要傳參數,故函數的雙括號能夠省略 --> <button v-on:click="decrement()">-</button> </div> <script> let app = new Vue({ el: '#app', data: { counter: 0 }, methods: { increment(){ this.counter++ }, decrement(){ this.counter-- } } }); </script> </body>
<body> <div id="app"> <!-- 不須要傳參數,故函數的雙括號能夠省略 --> <button @click="btn0Click">+</button> <!-- 不傳參數,會顯示event對象 --> <button @click="btn1Click()">+</button> <!-- 帶括號傳參數 --> <button @click="btn2Click(value)">+</button> <!-- 定義方法時,咱們既須要傳參數,又須要獲取到event對象,能夠經過$event得到event對象 --> <button @click="btn3Click(value, $event)">+</button> </div> <script> let app = new Vue({ el: '#app', data: { value: 13 }, methods: { btn0Click() { console.log("btn1Click"); }, btn1Click() { console.log("======", event); }, btn2Click(value) { console.log("------", value); }, btn3Click(value, event) { console.log("+++++", value, event); } }, }); </script> </body>
<body> <div id="app"> <!-- 1. .stop修飾符的使用:阻止單擊事件繼續傳播給後續定義的函數 --> <div @click="divClick"> <button @click.stop="btnClick">點擊</button> </div> <!-- 2. .prevent修飾符的使用:阻止事件的自帶默認行爲, --> <form action=""> <input type="submit" value="提交" @click.prevent="submitClick"></button> </form> <!-- 3. .keyup修飾符的使用:當鍵盤被釋放時觸發事件 --> <input @keyup="keyup">鬆開</input> <br> <input @click.keyup="keyup">鼠標點擊鬆開</input> <br> <!-- 3. .enter修飾符的使用:當鍵盤按下回車鍵觸發事件 --> <input @keyup.enter="enter">回車</input> <br> <!-- 4. .once修飾符的使用: 只能觸發一次回調 --> <button @click.once="once">只能點擊一次</button> </div> <script> let app = new Vue({ el: '#app', data: { }, methods: { btnClick(){ console.log("btnClick") }, divClick(){ console.log("divClick") }, submitClick(){ console.log("submitClick") }, keyup(){ console.log("keyup") }, enter(){ console.log("enter") }, once(){ console.log("once") } } }); </script> </body>
<body> <div id="app"> <!-- 從控制檯輸入 app.isShow = false就能夠將其隱藏 --> <h2 v-if="isShow"> <div>abc</div> <div>abc</div> <div>abc</div> <div>abc</div> <div>abc</div> {{message}} </h2> </div> <script> let app = new Vue({ el: '#app', data: { message: '哈哈', isShow: true }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 從控制檯輸入 app.isShow = false就能夠將其隱藏 --> <h2 v-if="isShow"> <div>abc</div> <div>abc</div> <div>abc</div> <div>abc</div> <div>abc</div> {{message}} </h2> <h2 v-else>當v-if爲false的時候,我就開始顯示了,我和v-if要緊連着使用</h2> </div> <script> let app = new Vue({ el: '#app', data: { message: '哈哈', isShow: true }, methods: { } }); </script> </body>
<body> <div id="app"> <p v-if="score >= 90">優秀</p> <p v-else-if="score >= 80">良好</p> <p v-else-if="score >= 60">及格</p> <p v-else>不及格</p> </div> <script> let app = new Vue({ el: '#app', data: { score: 99 } }); </script> </body>
<body> <div id="app"> <span v-if="isShowUserName"> <label for="userName">用戶名</label> <input type="text" id="userName" placeholder="請輸入用戶名"> </span> <span v-else> <label for="email">用戶郵箱</label> <input type="text" id="email" placeholder="請輸入用戶郵箱"> </span> <button @click="isShowUser">切換類型1</button> <button @click="isShowUserName = !isShowUserName">切換類型2</button> </div> <script> let app = new Vue({ el: '#app', data: { isShowUserName: true }, methods: { isShowUser() { this.isShowUserName = !this.isShowUserName } } }); </script> </body>
<body> <div id="app"> <!-- 注意:Vue在進行DOM渲染時,出於性能考慮,會盡量的複用先前的input框,而不是從新建立元素 如若咱們不須要複用input框,只須要添加一個 key就好,相同的key值纔會複用 --> <span v-if="isShowUserName"> <!-- label中的for指向input後,點擊label能夠將光標聚焦給input框 --> <label for="userName">用戶名</label> <input type="text" id="userName" placeholder="請輸入用戶名" key="userName"> </span> <span v-else> <label for="email">用戶郵箱</label> <input type="text" id="email" placeholder="請輸入用戶郵箱" key="userName"> </span> <button @click="isShowUser">切換類型1</button> </div> <script> let app = new Vue({ el: '#app', data: { isShowUserName: true }, methods: { isShowUser() { this.isShowUserName = !this.isShowUserName, //第二種方式:使用js將input框值清空 document.getElementById("userName").value = ''; document.getElementById("email").value = ''; } } }); </script> </body>
<body> <div id="app"> <!-- v-if 和 v-show的區別: v-if爲false的時候,壓根不會存在dom裏面, v-show爲false的時候,只是會增長個行內樣式:display:none; 建議: 若是須要頻繁切換的時候,使用v-show, 只有一次切換時一般使用v-if --> <span v-if="isShow" id="isShow">V-if</span> <span v-show="isShow" id="VShow">V-show</span> </div> <script> const app = new Vue({ el: '#app', data: { isShow: true }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 1.簡單遍歷數組 --> <ul> <li v-for="item in movies">{{item}}</li> </ul> <br> <!-- 2.帶索引遍歷數組 --> <ul> <li v-for="(item, index) in movies">{{index + 1}}.{{item}}</li> </ul> <br> <!-- 3.帶索引遍歷數組,且添加監聽事件 --> <ul> <li v-for="(item, index) in movies" @click="showIndex(index)">{{index + 1}}.{{item}}</li> </ul> </div> <script> const app = new Vue({ el: '#app', data: { movies: ['海王', '大話西遊', '星際爭霸', '三傻大鬧寶萊塢'] }, methods: { showIndex(index) { console.log('第' + (index + 1) + '個值'); } } }); </script> </body>
<body> <div id="app"> <!-- 1.在遍歷對象的過程當中,若是隻是得到一個值,那麼獲取到的就是整個對象的value值 --> <ul> <li v-for="item in obj">{{item}}</li> </ul> <br> <!-- 2.在遍歷對象的同時附帶格式:value和key (value, key) --> <ul> <li v-for="(item, key) in obj">{{item}}--{{key}}</li> </ul> <br> <!-- 3.在遍歷對象的同時附帶格式:value和key和index (value, key, index) --> <ul> <li v-for="(value, key, index) in obj">{{value}}--{{key}}--{{index+1}}</li> </ul> <br> </div> <script> const app = new Vue({ el: '#app', data: { obj: { id: 12, name: 'Luck', height: 1.78 } }, methods: { } }); </script> </body>
<body> <!-- splice() 方法向/從數組中添加/刪除項目,而後返回被刪除的項目。 1.app.obj.splice(4) 去除數組第五個值 2.app.obj.splice(3,0,'F') 在數組第四個值的時候添加F --> <div id="app"> <ul> <!-- 不添加key屬性: 在數組中間插入數據,須要將插入位置後面的值都後移,效率慢 --> <!-- 添加key屬性:相似於鏈表同樣,我插入中間只須要將兩端值的指向指給我,效率高--> <li v-for="item in obj" :key="item">{{item}}</li> </ul> </div> <script> const app = new Vue({ el: '#app', data: { obj: ['A', 'B', 'C', 'D', 'E'] }, methods: { } }); </script> </body>
<body> <div id="app"> <ul> <li v-for="item in obj" :key="item">{{item}}</li> </ul> <button @click="btnClick">點擊</button> </div> <script> let myDate = new Date(); const app = new Vue({ el: '#app', data: { obj: ['R', 'C', 'B', 'D', 'E'], }, methods: { btnClick() { //1.push()方法 // this.obj.push('F') //2.pop()方法,從末尾依次刪除 // this.obj.pop() //3.shift()方法,從頭開始依次刪除 // this.obj.shift() //4.unshift(),從頭開始依次添加元素 // this.obj.unshift('G','L') //5.splice(),方法向/從數組中添加/刪除/替換元素,而後返回被刪除的項目。 //this.obj.splice(4) //去除數組第五個值 //6.sort(),對數組的元素進行排序 // this.obj.sort() //7.reverse(),對數組進行反轉 // this.obj.reverse() //注意:經過索引值修改數組中的元素方法,不可取,vue不會幫我渲染修改後的值 // this.obj[0] = 'M' //解決方法: //刪除第五個 // this.obj.splice(3, 4, 'N') //①:在第三個位置修改爲 N // this.obj.splice(2, 1, 'N') //②:建議:Vue自帶的修改方法 Vue.set(this.obj, 2, 'G') } } }); </script> </body>
<body> <div id="app"> <ul> <!-- 對遍歷出來的結果列表,我能實現點擊列表對應的值,能讓它變成紅色 --> <li v-for="(item, index) in obj" :key="item" :class="{active: currentIndex === index}" @click="changeColor(index)">{{item}}</li> </ul> </div> <script> let myDate = new Date(); const app = new Vue({ el: '#app', data: { obj: ['R', 'C', 'B', 'D', 'E'], currentIndex: 0 }, methods: { changeColor(index) { this.currentIndex = index; } } }); </script> </body>
// javascript的高階函數: const nums = [10, 20, 30, 40, 50]; // 編程式範式:命令式編程/聲明式編程 // 編程式編程(第一公民:對象),函數式編程(第一公民:函數) // filter/map/reduce高階函數 // ①: // filter高階函數的使用: 它的回調函數有一個要求,必須返回一個boolean值 // true:當返回true時,函數內部會自動將此次回調的n加入到新的數組中去 // false:當返回false時,函數內部會過濾掉此次的 n let newNum1 = nums.filter(function (n) { return n < 100; }) console.log('newNum1==filter==' + newNum1); // ②: // map高階函數的使用 let newNum2 = newNum1.map(function (n) { return n * 2; }) console.log('newNum2==map==' + newNum2); let newNum21 = nums.map(function (n) { // 判斷條件無效,輸出結果與上面同樣,看來仍是須要filter來過濾 if (n < 80) { return n * 2; } else { return; } }) console.log('newNum21==map==' + newNum21); // ③: //6.reduce高階函數的使用: 對數組中的全部數據進行彙總(相加,相乘......) let total = newNum2.reduce(function (preValue, value) { return preValue + value; }, 0) console.log('total===' + total); // 長度爲 5 // preValue value //第一次: 0 20 //第二次: 20 40 //第三次: 60 60 //第四次: 120 80 //第五次: 200 100 //輸出 300 //④:將上面三個函數綜合起來使用: let sum = nums.filter(function (n) { return n < 50 }).map(function (n) { return n * 2 }).reduce(function (preValue, value) { return preValue + value }, 0) console.log('sum===' + sum); //⑤:使用箭頭函數將上面三個函數綜合起來使用(相似lombda表達式) let sum1 = nums.filter(n => n < 50).map(n => n * 2).reduce((pre, value) => pre + value); console.log('sum1===' + sum1);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="style.css"> </head> <body> <div id="app"> <div v-if="isFull"> <table> <thead> <tr> <th>編號</th> <th>書名</th> <th>出版日期</th> <th>價格</th> <th>數量</th> <th>操做</th> </tr> </thead> <tbody> <tr v-for="(item,index) in books" :class="{changeColor: number == 1}" @mouseenter="change(index)" @mouseleave="remove(index)"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <!-- 使用函數:<td>{{getfinalPrice(item.price)}}</td> --> <!-- 使用過濾器: --> <td>{{item.price | showPrice}}</td> <td> <button @click="subBtn(index)">-</button> {{item.count}} <button @click="addBtn(index)">+</button> </td> <td> <button v-if="exchange" @click="addItemBtn(index)">新增</button> <button v-else @click="removeBtn(index)">移除</button> <button @click="changeType()">切換類型</button> </td> </tr> </tbody> </table> <br> <span>總價格:{{showTotalPrice | showPrice}}</span> </div> <h2 v-else>購物車清空</h2> </div> </body> <script src="../js/vue.js"></script> <script src="main.js"></script> </html>
const app = new Vue({ el: '#app', data: { books: [{ id: 1, name: '算法導論', date: '2019-2', price: 87.21, count: 1, exchange: true }, { id: 2, name: 'UNIX編程藝術', date: '2019-4', price: 97.21, count: 2, exchange: true }, { id: 3, name: '編程珠璣', date: '2012-2', price: 77.21, count: 1, exchange: true }, { id: 4, name: '大話西遊', date: '2019-7', price: 100, count: 1, exchange: true } ], number: 2, exchange: false, isFull: true }, computed: { showTotalPrice() { let totalPrice = 0; //1.普通for循環 // for (let i = 0; i < this.books.length; i++) { // totalPrice += this.books[i].price * this.books[i].count // } // return totalPrice //2.index是索引 // for (let index in this.books) { // totalPrice += this.books[index].price * this.books[index].count // } //3.for of // for (let item of this.books) { // totalPrice += item.price * item.count // } //4.利用reduce函數來寫 return this.books.reduce(function (preValue, book) { return preValue + book.price * book.count }, 0) return totalPrice } }, methods: { // 行內按鈕操做 subBtn(index) { if (this.books[index].count > 0) { this.books[index].count-- } }, addBtn(index) { this.books[index].count++ }, removeBtn(index) { this.books.splice(index, 1) if (this.books.length <= 0) { this.isFull = !this.isFull } }, // 鼠標移動進區域,改變背景顏色 change(index) { // this this.number = 1; this.active = ".changeColor{ background-color: #cae6e6}" }, remove(index) { this.number = 2 }, // 改變按鈕類型 changeType() { this.exchange = !this.exchange }, addItemBtn() { const obj = [5, '數值分析', '2018-8', 96.10, 2]; this.books.push(obj) }, // 格式化價格 getfinalPrice(price) { return '¥' + price.toFixed(2); } }, filters: { showPrice(price) { //.toFixed(2):保留小數點後兩位 return '¥' + price.toFixed(2); } } })
table { border: 1px solid #cccccc; /* 消除表格的邊框內距 */ border-collapse: collapse; border-spacing: 0; width: 700px; } table thead { background-color: lightskyblue; } /* table tr:hover { background-color: pink; } */ table tr th { border: 1px solid #cccccc; } table tr td { border: 1px solid #cccccc; text-align: center; padding: 20px; } .changeColor { background-color: #cae6e6 }
<body> <div id="app"> <!-- v-model的基本使用 --> <input type="text" v-model="message">{{message}} <br> <!-- v-model的原理: --> <!-- 監聽input內容改變事件 --> <input type="text" v-on:input="changeInput($event)"> <input type="text" @input="changeInput"> <br> <!-- 此方法:input中會直接有message的值 , 其中target是事件源--> <input type="text" v-bind:value="message" v-on:input="message = $event.target.value"> <input type="text" :value="message" @input="message = $event.target.value"> </div> <script> const app = new Vue({ el: '#app', data: { message: '你好呀' }, methods: { changeInput(event) { this.message = event.target.value; } } }); </script> </body>
<body> <div id="app"> <!-- name要一致,否則選擇一個單選框,再選擇另外一個,以前那個仍是被選中狀態 --> <label for="male"> <input type="radio" name="sex" value="男" id="male" v-model="message">男 </label> <label for="female"> <input type="radio" name="sex" value="女" id="female" v-model="message">女 </label> <br> {{'你選中的值:' + message}} </div> <script> const app = new Vue({ el: '#app', data: { message: '' }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 單個多選框: 贊成協議示範 --> <label for="agreeLisence"> <input type="checkbox" v-model="isAgree">統一協議 </label> <button :disabled="!isAgree">下一步</button> <br> <!-- 多個多選框:愛好 --> <input type="checkbox" value="唱" v-model="hobbies">唱 <input type="checkbox" value="跳" v-model="hobbies">跳 <input type="checkbox" value="rap" v-model="hobbies">rap <input type="checkbox" value="打籃球" v-model="hobbies">打籃球 你選擇的興趣愛好是:{{hobbies}} </div> <script> const app = new Vue({ el: '#app', data: { isAgree: false, //單選框 hobbies: [] //多選框 }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 下拉框的單個使用 --> <select name="demo" v-model="fruit"> <option value="香蕉">香蕉</option> <option value="蘋果">蘋果</option> <option value="葡萄">葡萄</option> <option value="梨子">梨子</option> </select> <h3>你選擇的水果是:{{fruit}}</h3> <br> <!-- 下拉框的多個選中使用: 注意添加multiple,而後選擇多個須要按住ctrl鍵 --> <select name="demo" v-model="fruits" multiple> <option value="香蕉">香蕉</option> <option value="蘋果">蘋果</option> <option value="葡萄">葡萄</option> <option value="梨子">梨子</option> </select> <h3>你選擇的水果是:{{fruits}}</h3> </div> <script> const app = new Vue({ el: '#app', data: { fruit: '香蕉', fruits: [] }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 單個多選框: 贊成協議示範 --> <label v-for="(item, index) in originalHobbies"> <!-- 若是綁定originalHobbies,點擊下對應的多選框就會消失 --> <input type="checkbox" v-model="hobbies" :id="index+1" :value="item">{{item}} </label> 你選擇的興趣愛好是:{{hobbies}} </div> <script> const app = new Vue({ el: '#app', data: { isAgree: false, //單選框 hobbies: [], //多選框 originalHobbies: ['唱', '跳', 'rap', '打籃球'] }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- 1.lazy修飾符: 懶加載,可讓數據被按下回車失去焦點後纔會更新 --> <input type="text" v-model.lazy="message">{{message}} <hr> <!-- 2.number修飾符:能夠將 只能輸入數字 的類型轉換成String --> <input type="number" v-model="age"> <h3>{{age}}--{{typeof age}}</h3> <!-- 若是不想轉換成String類型,只要添加 .number --> <input type="number" v-model.number="height"> <h3>{{height}}--{{typeof height}}</h3> <hr> <!-- 3.去掉兩端的空格 --> <input type="text" v-model.trim="name"> <!-- 添加多個修飾符只需疊加後面就行,無前後順序要求 --> <input type="number" v-model.lazy.number="height"> <h3>{{name}}</h3> </div> <script> const app = new Vue({ el: '#app', data: { message: '你好呀', age: 0, height: 1, name: '' }, methods: { } }); </script> </body>
<body> <div id="app"> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> <script> // 建立組件構造器 const cpnC = Vue.extend({ // ES6語法:` 號能夠支持內容裏面換行比 ''更好使用 //若是有多個標籤使用,必須有個div包裹起來,不然內容顯示不徹底 template: ` <div> <h2>組件化</h2> <h3>我是,哈哈哈哈</h3> <h3>我是,呵呵呵呵</h3> </div> ` }) // 註冊組件 Vue.component('my-cpn', cpnC) const app = new Vue({ el: '#app', data: { }, methods: { } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn></cpn> <cpn></cpn> </div> <div id="app2"> <cpn></cpn> </div> <script> const cpnC = Vue.extend({ template: ` <div> <h2>組件化</h2> <h3>我是,哈哈哈哈</h3> <h3>我是,呵呵呵呵</h3> </div> ` }) // 註冊全局組件 Vue.component("cpn", cpnC) const app = new Vue({ el: '#app', data: { }, components: { // 註冊局部組件,即只能在app裏使用cpn這個組件 cpn: cpnC } }); const app2 = new Vue({ el: '#app2', }); </script> </body>
<body> <div id="app"> <cpn2></cpn2> </div> <script> const cpnC = Vue.extend({ template: ` <div> <h2>子組件</h2> <h3>我是,哈哈哈哈</h3> <h3>我是,呵呵呵呵</h3> </div> ` }) // 父組件:root組件 const cpnC2 = Vue.extend({ template: ` <div> <h2>父組件</h2> <h3>我是,哈哈哈哈</h3> <h3>我是,呵呵呵呵</h3> // 這個子組件須要先註冊 <cpn1><cpn1/> </div> `, components: { cpn1: cpnC } }) // 註冊全局組件 Vue.component("cpn", cpnC) const app = new Vue({ el: '#app', data: { }, components: { // 註冊局部組件,即只能在app裏使用這個組件 cpn1: cpnC, cpn2: cpnC2 } }); </script> </body>
<body> <div id="app"> <cpn1></cpn1> <cpn2></cpn2> </div> <script> // const cpnC = Vue.extend() // 語法糖註冊全局組件 Vue.component("cpn1", { template: ` <div> <h2>我是cpn1</h2> <h3>我是,哈哈哈哈</h3> </div> ` }) const app = new Vue({ el: '#app', data: { }, components: { // 語法糖註冊局部組件,即只能在app裏使用這個組件 'cpn2': { template: ` <div> <h2>我是cpn2</h2> <h3>我是,呵呵呵呵</h3> </div> ` } } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <cpn1></cpn1> </div> <!-- 1.使用script標籤:注意類型須要添加:text/x-template --> <script type="text/x-template" id="cpn"> <div> <h2>我是cpn1</h2> <h3>我是,哈哈哈哈</h3> </div> </script> <!-- 2.使用template標籤(推薦) --> <template id="cpn1"> <div> <h2>我是cpn1</h2> <h3>我是,哈哈哈哈</h3> </div> </template> <script> // const cpnC = Vue.extend() // 語法糖註冊全局組件 Vue.component("cpn", { // '#cpn' template: '#cpn1' }) const app = new Vue({ el: '#app', data: { } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <cpn></cpn> </div> <template id="cpn1"> <div> <h2>我是cpn1</h2> <h3>我是,哈哈哈哈</h3> <!-- 想要獲取title,必須在組件裏面定義一個函數,且有返回值 --> <h3>{{title}}</h3> </div> </template> <script> // const cpnC = Vue.extend() // 語法糖註冊全局組件 Vue.component("cpn", { // '#cpn' template: '#cpn1', data() { return { title: '好好學習,每天向上' } } }) const app = new Vue({ el: '#app', data: { // 模板裏的title不能獲取到此值 title: '好好學習,每天向上' } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <cpn></cpn> <hr> <cpn1></cpn1> <cpn1></cpn1> </div> <template id="cpn1"> <div> <h3>當前計數:{{count}}</h3> <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <template id="cpn2"> <div> <h3>當前計數:{{count}}</h3> <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <script> // 推薦:count數據不會共享 // 使用data函數:不會引發連鎖反應。即每一個都是個新對象,值地址不同, Vue.component("cpn", { // '#cpn' template: '#cpn1', data() { return { count: 0 } }, methods: { increment() { this.count++ }, decrement() { this.count-- } } }) // count數據共享 // 都是使用的這個obj常量 const obj = { count: 0 }; Vue.component("cpn1", { // '#cpn' template: '#cpn2', data() { return obj }, methods: { increment() { this.count++ }, decrement() { this.count-- } } }) const app = new Vue({ el: '#app', }); </script> </body>
<body> <div id="app"> {{movies.toString()}} <hr> <!-- 添加了前綴v-bind,vue會幫咱們解析movies,不會當成字符串處理 --> <cpn v-bind:vmoives="movies" :vmessage="message"></cpn> <hr> <!-- 當成字符串處理 --> <cpn vmoives="movies" vmessage="message"></cpn> </div> <template id="cpn"> <div> <h2>{{vmessage}}</h2> <ul v-for="(item,index) in vmoives"> <li>{{index}}.{{item}}</li> </ul> </div> </template> <script> const cpn = { template: '#cpn', props: ['vmoives', 'vmessage'], //這種實際上是表示變量名字,不能當成字符串 data() { return {} }, methods: { } } // 註冊全局組件 // Vue.component('cpn', cpn) const app = new Vue({ el: '#app', data: { movies: ['海王', '海賊王', '航空母艦'], message: '真香' }, components: { // ES6中的高階寫法,等同於 cpn: cpn cpn } }); </script> </body>
<body> <div id="app"> {{movies.toString()}} <hr> <cpn v-bind:propF="movies" :propC="message"></cpn> <hr> </div> <template id="cpn"> <div> <h2>{{propC}}</h2> <ul v-for="(item,index) in propF"> <li>{{index}}.{{item}}</li> </ul> </div> </template> <script> const cpn = { template: '#cpn', props: { // 基礎的類型檢查('null'匹配任何類型) propA: Number, // 多個可能的類型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true, default: '你好呀' }, // 帶有默認值的數字 propD: { type: Number, default: 100 }, // 注意:類型是對象/數組時,默認值必須是一個函數 // 帶有默認值的對象 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 帶有默認值的對象 propF: { type: Array, default() { return ['大話西遊', '造夢西遊'] } }, // 自定義驗證函數 propG: { validator: function (value) { // 這個值必須匹配下列字符串的一個 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } }, data() { return {} } } const app = new Vue({ el: '#app', data: { movies: ['海王', '海賊王', '航空母艦'], message: '真香' }, components: { cpn } }); </script> </body>
<body> <div id="app"> <cpn v-bind:prop-f="movies" v-bind:prop-g="message"></cpn> <hr> </div> <template id="cpn"> <div> <h2>{{propG}}</h2> <ul v-for="(item,index) in propF"> <li>{{index}}.{{item}}</li> </ul> </div> </template> <script> const cpn = { template: '#cpn', props: { // 帶有默認值的對象 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 帶有默認值的對象 propF: { type: Array, default() { return ['大話西遊', '造夢西遊'] } }, // 自定義驗證函數 propG: { validator: function (value) { // 這個值必須匹配下列字符串的一個:若是要檢索的字符串值沒有出現,則該方法返回 -1。 console.log(['success', 'warning', 'danger'].indexOf(value) !== -1); // 校驗失敗:Invalid prop: custom validator check failed for prop "propG". return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } }, data() { return {} } } const app = new Vue({ el: '#app', data: { movies: ['海王', '海賊王', '航空母艦'], message: 'succe' }, components: { cpn } }); </script> </body>
<body> <div id="app"> <!-- cpnClick在父組件中定義的方法 --> <cpn v-on:item-click="cpnClick"></cpn> <hr> <cpn @item-click="cpnClick($event)"></cpn> </div> <template id="cpn"> <div> <button v-for="(item,index) in categories" @click="btnClick(item)">{{item.name}}</button> </div> </template> <script> /*步驟: 1.子組件:觸發監聽的事件,好比被點擊了, 2.而後發送自定義事件this.$emit('cpn中的自定義事件名', item) 3.調用Vue中的事件監聽函數,如若在html文件中,不餓能使用駝峯命名自定義函數 */ // 子組件 const cpn = { template: '#cpn', data() { return { categories: [ {id: 'a1', name: '熱門推薦'}, {id: 'a2', name: '手機數碼'}, {id: 'a3', name: '家用家電'}, {id: 'a4', name: '電腦辦公'} ] } }, methods: { btnClick(item) { //發射事件:自定義事件(父組件的cpn中接收此事件的名字) // html不區分大小寫,這裏不能使用駝峯命名 this.$emit('item-click', item) } } } // <!-- 父組件 --> const app = new Vue({ el: '#app', components: { cpn }, methods: { cpnClick(item) { console.log('cpnClick', item); } }, }); </script> </body>
<body> <div id="app"> <cpn :number1="num1" :number2="num2"></cpn> </div> <template id="cpn"> <div> <h2>雙向綁定的是num1:{{dnum1}}</h2> <h2>props:{{number1}}</h2> <input type="text" v-model="dnum1"> <h2>雙向綁定的是num2:{{dnum2}}</h2> <h2>props:{{number2}}</h2> <input type="text" v-model="dnum2"> </div> </template> <script> const app = new Vue({ el: '#app', data: { num1: 0, num2: 1 }, components: { cpn: { template: '#cpn', props: { number1: Number, number2: Number }, data() { return { /* Property or method "num2" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property 即須要添加data(){} */ dnum1: this.number1, dnum2: this.number2 } } } }, methods: { } }); </script> </body>
<body> <div id="app"> <!-- number1的值來源與Vue中data的num1 可是在組件中取值要用{{number1}},也就是props對應的值--> <cpn :number1="num1" :number2="num2" @change1props="change1props" @change2props="change2props"></cpn> <!-- 3.父組件接收傳過來的自定義事件,Vue中的 "change2props"方法 --> </div> <template id="cpn"> <div> <h2>雙向綁定的是num1:{{dnum1}}</h2> <h2>props:{{number1}}</h2> <!-- 這方式同 v-model: 監聽input框,調用組件中的 changeInputValue1事件 --> <input type="text" :value="dnum1" @input="changeInputValue1"> <h2>雙向綁定的是num2:{{dnum2}}</h2> <h2>props:{{number2}}</h2> <input type="text" :value="dnum2" @input="changeInputValue2"> </div> </template> <script> const app = new Vue({ el: '#app', data: { num1: 0, num2: 1 }, components: { cpn: { template: '#cpn', props: { number1: Number, number2: Number }, data() { return { dnum1: this.number1, dnum2: this.number2 } }, methods: { changeInputValue1(event) { // 1.將input的值賦值到 dnum1 中去 this.dnum1 = event.target.value; // 2.爲了讓父組件能夠修改值,發送一個事件 this.$emit('change1props', this.dnum1) // 將下面輸入框的props值: 變成1/2 this.dnum2 = this.dnum1 / 2 this.$emit('change2props', this.dnum2) }, changeInputValue2() { this.dnum2 = event.target.value; this.$emit('change2props', this.dnum2) // 將上面輸入框的props值: 變成2倍 this.dnum1 = this.dnum2 * 2 this.$emit('change1props', this.dnum1) } }, } }, methods: { change1props(value) { // 改變 prop 中的num1的值 console.log('dum1' + value); this.num1 = parseFloat(value); }, change2props(value) { console.log('dum2' + value); this.num2 = parseFloat(value); } } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn ref="refA"></cpn> <button @click="btnClick">按鈕</button> </div> <template id="cpn"> <div> 我是子組件 </div> </template> <script> const app = new Vue({ el: '#app', data: { message: 'Lemon' }, methods: { btnClick() { // 1. $.chlidren for (let item of this.$children) { console.log(item.name); item.showMessage() } // 2. $.refs: 僅僅會調動帶有refs標示的 // 這樣有時候咱們想即便在新增數據後,依舊能操控它 console.log('refs' + this.$refs.refA.name); } }, components: { cpn: { template: '#cpn', data() { return { name: 'Lemon', id: 1, height: 1.78 } }, methods: { showMessage() { console.log(this.id); } }, } } }); </script> </body>
<body> <div id="app"> <cpn></cpn> <hr> <ccpn></ccpn> </div> <template id="cpn"> <div>我是cpn子組件</div> </template> <!-- cpn的子組件 --> <template id="ccpn"> <div> <h3>我是cpn的子組件</h3> <button @click="btnClick">ccpn按鈕</button> </div> </template> <script> const ccpn = Vue.component('ccpn', { template: '#ccpn', methods: { btnClick() { // 按理這個是cpn的子組件,this應該指ccpn對象, // 調用this.$parent時,訪問的是ccpn的父組件cpn,即返回對象是vuecomponents // 調用this.$root時,訪問的才應該是cpn的父組件,即返回對象是vue // 但是我放在cpn的components裏說ccpn沒有註冊 console.log('ccpn=', this.$root.message) } } }) const app = new Vue({ el: '#app', data: { message: 'Lemon' }, methods: { }, components: { cpn: { template: '#cpn', data() { return { name: '我是cpn的name' } }, components: { ccpn } } } }); </script> </body>
<body> <!-- 1.插槽的基本使用:<slot></slot> 2.插槽的默認值:<slot>傳的元素/值:eg 哈哈哈</slot> 3.若是有多個值,同時被放入到組件中進行替換,會一塊兒做爲替換元素 --> <div id="app"> <cpn>嘻嘻嘻</cpn> <cpn><button>按鈕</button></cpn> <cpn>哈哈哈</cpn> <cpn></cpn> </div> <template id="cpn"> <div> <h3>組件化開發</h3> <slot><button>按鈕</button></slot> </div> </template> <script> const app = new Vue({ el: '#app', data: { }, methods: { }, components: { cpn: { template: '#cpn' } } }); </script> </body>
<body> <div id="app"> <cpn>嘻嘻嘻</cpn> <cpn><span slot="right">哈哈哈</span></cpn> </div> <template id="cpn"> <div> <slot name="left">左邊</slot> <slot name="center">中間</slot> <slot name="right">右邊</slot> <slot>右邊</slot> </div> </template> <script> const app = new Vue({ el: '#app', data: { }, methods: { }, components: { cpn: { template: '#cpn' } } }); </script> </body>
<body> <!-- 總結: 父組件模板的全部東西都會在父級做用域內編譯 子組件模板的全部東西都會在子級做用域內編譯 --> <div id="app"> <!-- 這個裏面的isShow會先從所在模板裏面順下去找,即從Vue裏找尋, 所以Vue中的data的isShow才能影響顯示與否 --> <cpn v-show="isShow"></cpn> </div> <template id="cpn"> <div> <h2>我是組件</h2> <!-- 這個裏面的isShowCpn會先從所在模板裏面順下去找,即從cpn裏找尋, --> <h3 v-show="isShowCpn">我是哈哈哈</h3> </div> </template> <script> const app = new Vue({ el: '#app', data: { isShow: true }, methods: { }, components: { cpn: { template: '#cpn', data() { return { isShow: false, isShowCpn: true } } } } }); </script> </body>
<body> <!-- 做用域插槽:父組件替換插槽的標籤,可是內容由子組件來提供 --> <div id="app"> <cpn></cpn> <hr> <cpn> 哈哈哈哈· <!-- 目標得到子組件中的pLanguages --> <template> <div slot-scope="slot"> <span v-for="(item,index) in slot.data">- {{item}} {{item}} - </span> <hr> </div> </template> </cpn> <hr> <cpn> <!-- 目標得到子組件中的pLanguagesv-slot:todo todo指向slot中的name="todo" --> <template v-slot:todo="slotProps"> <div> 加join():<span>- {{slotProps.data.join(' - ')}}</span><br> <span>{{slotProps.data}}</span> </div> </template> </cpn> </div> <template id="cpn"> <div> <!-- :名字="cpn中對應須要獲取的值" --> <slot :data="pLanguages" name="todo"> <ul> <li v-for="(item,index) in pLanguages"> {{item}} </li> </ul> </slot> </div> </template> <script> const app = new Vue({ el: '#app', data: { }, methods: { }, components: { cpn: { template: '#cpn', data() { return { pLanguages: ['Java', 'C', 'C++', 'Python', 'C#'] } } } } }); </script> </body>
aaa.js
var name = '小紅' let age = 18 var flag = true function sum(num1, num2) { return num1 + num2 } if (flag) { console.log(sum(200, 300)); } export { flag, sum }
bbb.js
var name = '小紅' var flag = false // var name = '小明' // let age = 18 // var flag = true // function sum(num1, num2) { // return num1 + num2 // } // if (flag) { // console.log(sum(20, 30)); // } // export { // flag, sum // }
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!-- 出現了跨域的問題,可是原理基本這樣 --> <script src="aaa.js" type="module"></script> <script src="bbb.js" type="module"></script> <script src="mmm.js" type="module"></script> </body> </html>
mmm.js
import {flag} from "./aaa.js"; if (flag) { console.log('小明是天才,哈哈哈哈'); }
info.js
export const name = 'why' export const age = 18 export const height = 1.78
main.js
// 1.使用commonjs的模塊化規範 const {add, mul} = require('./mathUtils.js') console.log(add(20, 30)); console.log(mul(25, 30)); // 2.使用ES6的模塊化的規範 import {name, age, height} from "./info"; console.log(name); console.log(age); console.log(height);
mathUtils.js
function add(num1, num2) { return num1 + num2 } function mul(num1, num2) { return num1 * num2 } module.exports = { add, mul }
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!-- PS D:\Web_Study\vue.js學習> cd 12-webpack使用\1-webpack的起步 PS D:\Web_Study\vue.js學習\12-webpack使用\1-webpack的起步> webpack ./src/main.js ./dist/bundle.js --> <!-- 生成文件的位置 --> <script src="./dist/bundle.js"></script> </body> </html>
webpack.config.js
const path = require('path') // npm init; npm install module.exports = { entry: './src/main.js', output: { // 動態獲取路徑:resolve拼接地址 path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' }, }
package.json
{ "name": "meetwebpack", "version": "1.0.0", "description": "", "main": "webpack.config.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, "author": "", "license": "ISC", "devDependencies": { "webpack": "^3.6.0" } }
webpack.config.js
const path = require('path') // npm init; npm install module.exports = { entry: './src/main.js', output: { // 動態獲取路徑:resolve拼接地址 path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', // 能夠顯示加載後的圖片 // publicPath: '/dist' publicPath: 'dist/' }, module: { rules: [{ test: /\.css$/i, use: ['style-loader', 'css-loader'], }, { test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }, { test: /\.(png|jpg|gif)$/, use: [{ loader: 'url-loader', options: { // 若是limit小於文件大小 * 1024,就會報錯,Cannot find module 'file-loader' // 通常配置成8kb limit: 8192, name: 'img/[name].[hash:8].[ext]' } }] }, { test: /\.js$/, // 排除 exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['es2015'] } } } ], }, }
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!-- webpack官網:https://www.webpackjs.com/loaders/babel-loader/ 重命名會讓配置正確的出錯,須要從新安裝 如若出現,ERROR in Entry module not found: Error: Can't resolve 'babel-loader' in 'D:\Web_Study\vue.js學習\12-webpack使用\4-webpack配置vue' 請 cnpm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env webpack 0. 動態獲取webpack的dist配置路徑 //入口 entry: './src/main.js', //輸出 output: { // 動態獲取路徑:resolve拼接地址 path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, 使用 cnpm run build 啓動方式配值: 1.安裝本地webpack 2.在package.json文件中的script添加 "build": "webpack" 3.而後輸入cnpm run build,就會在webpack.config.js中根據動態路徑建立 4.加載css文件:cnpm install --save-dev css-loader 5.解析加載進去的css文件:cnpm install --save-dev style-loader 6.在webpack.config.js中的module.exports = {}中添加 module: { rules: [ { test: /\.css$/i, use: ['style-loader', 'css-loader'], }, ], }, 7.導入less文件,並轉換成css文件:cnpm install --save-dev less-loader less 8.在webpack.config.js中的module.exports = {}中添加 module: { rules: [{ test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }] } 9.加載圖片:cnpm install --save-dev url-loader 10.{ test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { // 若是limit小於文件大小 * 1024,就會報錯,Cannot find module 'file-loader' // 若是要加載的圖片小於8kb,就會將加載的圖片轉換成base64 // 通常配置成8kb limit:8192 } } ] } 11.404 會把圖片發佈在dist文件夾裏,可是咱們css文件中仍是在找img裏的圖片 GET file:///D:/Web_Study/vue.js%E5%AD%A6%E4%B9%A0/12-webpack%E4%BD%BF%E7%94%A8/4-webpack%E7%9A%84lcss%E6%A0%B7%E5%BC%8F- less%E6%96%87%E4%BB%B6/c67dcb9e8b50af7c2550f6da0c40f7e0.jpg net::ERR_FILE_NOT_FOUND 12. 解決方法:能夠顯示加載後的圖片 publicPath: '/dist' 在webpack.config.js中的output裏添加 // 能夠顯示加載後的圖片 publicPath: '/dist' 13. 讓加載後的圖片在dist裏的指定目錄: 圖片名字 img文件夾/[name]此爲變量名/hash爲32位,截取8位/ext:拓展名 注意:若只寫name就是固定值,即一直都是這個名字 name: 'img/[name].[hash:8].[ext]' 14. 顯示圖片:publicPath: 'dist/' 15. ES6語法 轉換成 ES5語法: ①:cnpm install --save-dev babel-loader@7 babel-core babel-preset-es2015 ②:配置文件中添加: module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] } --> <script src="./dist/bundle.js"></script> </body> </html>
main.js
// 1.使用commonjs的模塊化規範 const {add, mul} = require('./js/mathUtils.js') console.log(add(20, 30)); console.log(mul(25, 30)); // 2.使用ES6的模塊化的規範 import {name, age, height} from "./js/info"; console.log(name); console.log(age); console.log(height); // 3.依賴css文件 require('./css/normal.css') // 4.依賴less文件 require('./css/special.less') document.writeln('<h2>你好呀,李銀河</h2>')
info.js
export const name = 'why' export const age = 18 export const height = 1.78
mathUtils.js
function add(num1, num2) { return num1 + num2 } function mul(num1, num2) { return num1 * num2 } module.exports = { add, mul }
normal.css
body { /* background: mediumaquamarine; */ background: url("../img/timg1.jpg") }
special.less
@fontSize: 50px; @fontColor: orange; body { font-size: @fontSize; color: @fontColor }
模塊展現
App.vue
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'app', components: { HelloWorld } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
HelloWorld.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
main.js
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ // 使用的是runtime-only render: h => h(App), // render: h => { // return h(App) // } }).$mount('#app')