1. 組件的data為什么必須是函數(shù)巷疼?
組件中的 data 寫成一個函數(shù)抱婉,數(shù)據(jù)以函數(shù)返回值形式定義寻拂,這樣每復用一次組件,就會返回一份新的 data 逢艘,類似于給每個組件實例創(chuàng)建一個私有的數(shù)據(jù)空間旦袋,讓各個組件實例維護各自的數(shù)據(jù)。而單純的寫成對象形式它改,就使得所有組件實例共用了一份data疤孕,就會造成一個組件的值發(fā)生改變,全部組件都會變的結果央拖。
這樣的好處就是每各個組件可以維護各自的數(shù)據(jù)祭阀,如果 data 是一個對象則會影響到其他組件鹉戚。
2. 問 v-if 和 v-show 有什么區(qū)別?
相同點:v-if與v-show都可以動態(tài)控制dom元素顯示隱藏
不同點:v-if隱藏是將dom元素整個刪除,而v-show隱藏則是為該元素添加css--display:none专控,dom元素還在抹凳。
3. vue幾種常用的指令
v-text:元素的innerText屬性(不帶標簽)
v-html:元素的innerHTML屬性(帶標簽)
v-bind:綁定屬性
v-on:綁定事件,綁定的事件從methods中獲取
事件修飾符
.stop:阻止冒泡伦腐,調(diào)用 event.stopPropagation()
.prevent:阻止默認事件赢底,調(diào)用 event.preventDefault()
.capture:添加事件偵聽器時使用事件捕獲模式
v-model
作用:在表單元素上創(chuàng)建雙向數(shù)據(jù)綁定
說明:監(jiān)聽用戶的輸入事件以更新數(shù)據(jù)
所謂的雙向綁定,就是你在view視圖層里面改變了值柏蘑,vue里面對應的值也會改變幸冻。只能給具備value屬性的元素進行雙向數(shù)據(jù)綁定。
v-if 和 v-show
條件渲染
v-if:根據(jù)表達式的值的真假條件咳焚,銷毀或重建DOM元素
v-show:根據(jù)表達式之真假值洽损,切換元素的 display: block/none 屬性
v-for
作用:基于源數(shù)據(jù)多次渲染元素或模板塊,使用 v-for 的時候提供 key 屬性革半,可以提高列表渲染的效率趁啸,提高頁面的性能。
v-once 提升性能
說明:只渲染元素和組件一次督惰。隨后的重新渲染,元素/組件及其所有的子節(jié)點將被視為靜態(tài)內(nèi)容并跳過旅掂。這可以用于優(yōu)化更新性能赏胚。
4. 對于Vue是一套漸進式框架的理解
Vue.js是一個漸進式框架,只需要具備基本的HTML/CSS/JavaScript基礎就可以快速上手商虐。在用Vue.js構建大型應用時推薦使用NPM安裝觉阅,但是需要注意npm的版本需要大于3.0。
在通過npm安裝項目后秘车,我們需要對其目錄進行解析:
(1) build:項目構建(webpack)相關代碼;
(2) config:配置目錄典勇,包括端口號等。
(3) node_modules:npm加載的項目依賴模塊
(4) src:這個目錄當中的內(nèi)容包含了我們基本上要做的事情叮趴,這里包含了幾個文件:
(一)assets:存放圖片
(二)components:存放組件文件
(三)App.vue:項目入口文件割笙,組件也可以直接寫在這里不適用components
(四)main.js:核心文件
(5) static:靜態(tài)資源目錄
(6) test:初始測試目錄
(7) .xxxx:配置文件,包括git配置和語法配置等
(8) index.html:首頁
(9) package.json:項目配置文件
(10) README.md:說明文檔
Vue的mvvm框架給了前端一種思路:完全基于數(shù)據(jù)驅動眯亦,幫助你從繁雜的dom操作中解脫出來
使用Vue的過程就是定義MVVM各個組成部分過程的過程:
(1) 定義View
(2) 定義Model
(3) 創(chuàng)建一個Vue實例或“ViewModel”
在創(chuàng)建Vue實例的時候伤溉,需要傳入選項對象,可以包含掛載元素妻率、數(shù)據(jù)等乱顾。
Vue實例被創(chuàng)建前會經(jīng)過初始化,然后在數(shù)據(jù)變化時更新DOM宫静,在這個期間也會調(diào)用一些生命周期鉤子走净,從而我們可以自定義邏輯券时。總共可以分為8個段:
(1) beforeCreate 初始化實例后 數(shù)據(jù)觀測和事件配置之前調(diào)用
(2) created 實例創(chuàng)建完成后調(diào)用
(3) beforeMount 掛載開始前被用
(4) mounted el被新建vm.$el替換并掛在到實例上之后調(diào)用
(5) beforeUpdate 數(shù)據(jù)更新時調(diào)用
(6) updated 數(shù)據(jù)更改導致的DOM重新渲染后調(diào)用
(7) beforeDestory 實例被銷毀前調(diào)用
(8) destoryed 實例銷毀后調(diào)用
需要注意的是created和mounted的區(qū)別伏伯,created是實例已經(jīng)創(chuàng)建但未掛載骄崩,所以一些dom操作要放在mounted中。
Vue組件的API來自props(允許外部環(huán)境傳遞數(shù)據(jù)給組件)屈扎、events(允許組件觸發(fā)外部環(huán)境副作用)和slots(允許外部環(huán)境將額外的內(nèi)容組合在組件中)三個部分狡孔,組件的data屬性必須是函數(shù)。
漸進的理解:vue只是個輕量視圖而已蜓堕,只做自己該做的事抛虏,不做不該做的事。
5. vue中使用 v-for 時套才,綁定key的作用
可以提高列表渲染的效率迂猴,提升頁面的性能。
6. v-for 與 v-if 的優(yōu)先級
當 v-if 與 v-for 一起使用時背伴,v-for 具有比 v-if 更高的優(yōu)先級沸毁,這意味著 v-if 將分別重復運行于每個 v-for 循環(huán)中,所以傻寂,不推薦v-if和v-for同時使用息尺。
7. axios 解決跨域問題
一、使用腳手架創(chuàng)建好項目
全局安裝 vue-cli
npm install --global vue-cli
創(chuàng)建一個基于 webpack 模板的新項目
vue init webpack vue-demo
進入項目疾掰,安裝依賴搂誉,啟動項目
cd vue-demo
npm install
npm run dev
二、安裝axios静檬,并配置相應文件炭懊。這里跨域請求的接口來自豆瓣的api
安裝 npm install axios --save
配置:
1、在 src/main.js 中引入使用
import axios from 'axios';
Vue.prototype.$axios=axios;
2拂檩、在 config/index.js 中的 的dev 添加以下代碼侮腹,設置一下proxyTable;
proxyTable:{
'/api': {
target : 'https://movie.douban.com/', //設置你調(diào)用的接口域名和端口號.別忘了加http
changeOrigin : true, //允許跨域
pathRewrite : {
'^/api': ''
// '/'這里理解成用‘/api’代替target里面的地址稻励,后面組件中我們掉接口時直接用api代替父阻。比如我要調(diào)用'https://movie.douban.com/v2/movie/top250',直接寫‘/api/v2/movie/top250’即可.
}
}
},
3钉迷、在 config/dev.env.js 中設置以下代碼
module.exports = merge(prodEnv, {
NODE_ENV: '"development"', //開發(fā)環(huán)境
API_HOST: "/api/"
})
4至非、在 config/prod.env.js 中設置以下代碼
module.exports = {
NODE_ENV: '"production"',//生產(chǎn)環(huán)境
API_HOST: '"https://movie.douban.com/"'
}
5、修改 src/components/HelloWorld.vue 文件
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<ul>
<li v-for="item in movieArr">
<span>{{item.title}}</span>
</li>
</ul>
<button @click="sayOut">渲染</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
data() {
return {
msg: '調(diào)用豆瓣api',
movieArr : []
}
},
methods:{
sayOut () {
this.$axios.get('/').then((res) => {
console.log(res)
if (res.status == 200){
console.log(res.data)
// this.movieArr = res.data.subjects
}
// 這里要強調(diào)一下這個 this 箭頭函數(shù)指的是它的父級也就是vue實例 然后不用箭頭函數(shù)的話 this是一個undefined糠聪,無法給movieArr來賦值荒椭。
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
</style>
到此 axios 跨域成功解決。
8. axios 封裝http請求
- 在main.js 中引入
import axios from 'axios'
import {get, post, patch, put} from './config/http'
// 定義全局變量
Vue.prototype.$get=get;
Vue.prototype.$post=post;
Vue.prototype.$patch=patch;
Vue.prototype.$put=put;
2.src目錄下創(chuàng)建config文件夾舰蟆,config文件夾創(chuàng)建http.js
import axios from 'axios';
axios.defaults.timeout = 5000;
axios.defaults.baseURL ='';
//http request 攔截器
axios.interceptors.request.use(
config => {
// const token = getCookie('名稱');注意使用的時候需要引入cookie方法趣惠,推薦js-cookie
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/json;charset=UTF-8' // 處理json
// 'Content-Type':'application/x-www-form-urlencoded' // 處理hash
}
// if(token){
// config.params = {'token':token}
// }
return config;
},
error => {
return Promise.reject(err);
}
);
//http response 攔截器
axios.interceptors.response.use(
response => {
if(response.data.errCode ==2){
router.push({
path:"/login",
querry:{redirect:router.currentRoute.fullPath}//從哪個頁面跳轉
})
}
return response;
},
error => {
return Promise.reject(error)
}
)
/**
* 封裝get方法
* @param url
* @param data
* @returns {Promise}
*/
export function fetch(url,params={}){
return new Promise((resolve,reject) => {
axios.get(url,{
params:params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封裝post請求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url,data = {}){
return new Promise((resolve,reject) => {
axios.post(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封裝patch請求
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url,data = {}){
return new Promise((resolve,reject) => {
axios.patch(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封裝put請求
* @param url
* @param data
* @returns {Promise}
*/
export function put(url,data = {}){
return new Promise((resolve,reject) => {
axios.put(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
- 在項目的 config/index.js 解決跨域請求
proxyTable: {
'/apis': {
// target: 'http://39.105.189.51:8052',
target: 'http://api.edgvip.cn',
changeOrigin: true,
pathRewrite: {
'^/apis': ''
}
}
},
-
組件中引入使用
eg: 接口文檔為下圖
methods: {
login() {
this.$post('apis/api/user/login1',{mobilePhone: this.mobilePhone, password: this.password}).then((res) => {
// console.log(res)
if(res.rs == 1){
this.$toast(res.info);
this.$router.push('/home'); // 路由跳轉
}else{
this.$toast(res.info);
}
})
},
},
此時狸棍,完成axios的封裝。
9. vue 實現(xiàn)tab切換
其實就是路由的使用
- src下創(chuàng)建router文件夾味悄,內(nèi)部包含index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Home
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/news',
name: 'News',
component: News
}
]
})
- 在main.js 中引入router
import router from './router'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
- 在App.vue中使用
<template>
<div id="app">
<img src="./assets/logo.png">
<div>
<router-link to="/home">主頁</router-link>
<router-link to="/news">新聞</router-link>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style scoped>
</style>
10. 如何配置 vue 打包生成文件的路徑草戈?
- 將 config.js 文件下index.js中的assersPublishPath,改為‘./’
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
// 將 build 中的 assetsPublicPath 改為 './'侍瑟, 修改dev唐片,無效
assetsPublicPath: './',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
- 將build/utils.js 加入 publicPath: '../../'
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
// 在 utils.js 的此處加上下面代碼,即可
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
11. vue如何適配移動端涨颜?
在 main.js 引入 rem.js
import './config/rem'
rem.js 代碼如下:
window.onload = function() {
getRem(750, 100);
}
window.onresize = function() {
getRem(750, 100);
}
function getRem(pwidth, prem) {
var html = document.documentElement;
var oWidth = document.body.clientWidth || document.documentElement.clientWidth;
html.style.fontSize = oWidth/pwidth*prem + 'px';
}
12. vue如何優(yōu)化首屏加載速度费韭?
- 使用CDN資源,減小服務器帶寬壓力庭瑰;
- 將靜態(tài)js css放到其他地方(如OSS)星持,減小服務器壓力;
- 按需加載第三方UI資源弹灭;
- 服務端開啟gzip督暂,減小網(wǎng)絡傳輸?shù)牧髁看笮。?/li>
- 按照頁面或者組件分塊懶加載
13. vue.js的兩個核心思想
數(shù)據(jù)驅動 和 組件系統(tǒng)
14. vue數(shù)據(jù)的雙向綁定
在vue.js里面只需要改變數(shù)據(jù)穷吮,Vue.js通過directives指令去操作DOM元素逻翁,當數(shù)據(jù)發(fā)生變化,會通知指令去修改對應的DOM捡鱼,數(shù)據(jù)的變化驅動DOM的變化卢未,DOM是數(shù)據(jù)的一種映射。vue.js還會對DOM做一些監(jiān)聽(DOM Listener)堰汉,當我們修改視圖的時候,vue.js監(jiān)聽到這些變化伟墙,從而改變數(shù)據(jù)翘鸭。這樣就形成了數(shù)據(jù)的雙向綁定。
15. MVVM框架的理解
MVVM 由 Model戳葵、View就乓、ViewModel 三部分構成,Model 代表數(shù)據(jù)層拱烁;View 代表視圖層生蚁,它負責將數(shù)據(jù)模型轉化成UI 展現(xiàn)出來;ViewModel 是一個同步View 和 Model的實例對象戏自。
【model模型】指的是后端傳遞的數(shù)據(jù)邦投。【view視圖】指的是所看到的頁面擅笔≈疽拢【viewmodel視圖模型】是mvvm模式的核心屯援,它是連接view和model的橋梁。它有兩個方向:一是將【模型】轉化成【視圖】念脯,即將后端傳遞的數(shù)據(jù)轉化成所看到的頁面狞洋。實現(xiàn)的方式是:數(shù)據(jù)綁定。二是將【視圖】轉化成【模型】绿店,即將所看到的頁面轉化成后端的數(shù)據(jù)吉懊。實現(xiàn)的方式是:DOM 事件監(jiān)聽。這兩個方向都實現(xiàn)的假勿,我們稱之為數(shù)據(jù)的雙向綁定借嗽。
在MVVM模式下,View 和 Model 之間并沒有直接的聯(lián)系废登,而是通過ViewModel進行交互淹魄,Model 和 ViewModel 之間的交互是雙向的, 因此View 數(shù)據(jù)的變化會同步到Model中堡距,而Model 數(shù)據(jù)的變化也會立即反應到View 上甲锡。
15. 自定義指令和自定義過濾器
自定義指令
自定義指令的參數(shù)有:
el: 指令所綁定的元素,可以用來直接操作 DOM 羽戒。
binding: 一個對象缤沦,包含以下屬性:
name: 指令名,不包括 v- 前綴易稠。
value: 指令的綁定值缸废, 例如: v-my-directive="1 + 1", value 的值是 2。
oldValue: 指令綁定的前一個值驶社,僅在 update 和 componentUpdated 鉤子中可用企量。無論值是否改變都可用。
expression: 綁定值的字符串形式亡电。 例如 v-my-directive="1 + 1" 届巩, expression 的值是 "1 + 1"。
arg: 傳給指令的參數(shù)份乒。例如 v-my-directive:foo恕汇, arg 的值是 "foo"。
modifiers: 一個包含修飾符的對象或辖。 例如: v-my-directive.foo.bar, 修飾符對象 modifiers 的值是 { foo: true, bar: true }瘾英。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定義指令</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<div class="box" v-pos:red.left.top="true">自定義指令,背景色為紅色颂暇,固定在左上角</div>
<div class="box" v-pos.right.bottom="true">自定義指令缺谴,固定在右下角</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
},
directives: {
pos (el, binding){
console.log(el, binding);
// 修飾符 .left.top
var position = binding.modifiers;
// position = {left: true, top: true}
// 綁定的參數(shù) :red
var color = binding.arg;
if (binding.value){
el.style.position = 'fixed';
el.style.background = color;
for(let val in position){
el.style[val] = '10px'
}
}
}
}
})
</script>
</html>
自定義過濾器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定義指令</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<div><span>{{length}}m</span>=<span>{{length | meter("cm")}}</span></div>
<div>{{price | myCurrency('$')}}</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
length: 1,
price: 120
},
filters: {
meter (val, unit){
console.log(val, unit);
return val*100 + unit
},
myCurrency(val, unit) {
console.log(val, unit);
return unit + val
}
}
})
</script>
</html>
16. vue-cli 工程常用的 npm 命令有哪些?
下載 node_modules 資源包的命令:
npm install
// 安裝模塊耳鸯;
// -save-dev(-D) 是指將包信息添加到 package.json 里的 devDependencies節(jié)點瓣赂,表示開發(fā)時依賴的包榆骚。
npm install 模塊名 --save-dev(-D)
// -save(-S) 是指將包信息添加到 package.json 里的dependencies節(jié)點,表示發(fā)布時依賴的包煌集。
npm install 模塊名 --save(-S)
啟動 vue-cli 開發(fā)環(huán)境的 npm命令:
npm run dev
vue-cli 生成 生產(chǎn)環(huán)境部署資源 的 npm命令:
npm run build
用于查看 vue-cli 生產(chǎn)環(huán)境部署資源文件大小的 npm命令:
npm run build --report
17. vue常用的修飾符
<!-- 阻止單擊事件繼續(xù)傳播(阻止冒泡)-->
<div onclick="alert(2)">
<button class="btn" onclick="someEvents()">按鈕</button>
</div>
<script>
function someEvents(event) {
alert(1);
var event = event || window.event;
event.stopPropagation();
}
</script>
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 (默認事件) -->
// event.preventDefault(); //取消默認事件
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯(lián) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件監(jiān)聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發(fā)的事件先在此處處理妓肢,然后才交由內(nèi)部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發(fā)處理函數(shù) -->
<!-- 即事件不是從內(nèi)部元素觸發(fā)的 -->
<div v-on:click.self="doThat">...</div>
<!-- 在默認情況下,v-model 在每次 input 事件觸發(fā)后將輸入框的值與數(shù)據(jù)進行同步 苫纤。-->
<input v-model.lazy="msg" >
<!-- 自動將用戶的輸入值轉為數(shù)值類型碉钠,可以給 v-model 添加 number 修飾符 -->
<input v-model.number="num" >
<!-- 自動過濾用戶輸入的首尾空格 -->
<input v-model.trim="msg" />
18. vue事件中如何使用event對象?
<div>
<button id="btn" @click="click">click me</button>
<button @click="click()">click you</button>
<button @click="click($event)">click us</button><br/>
</div>
<script>
var vm = new Vue({
el: '#app',
methods: {
click() {
// 獲取當前 DOM 元素
var el = event.currentTarget;
// docuemnt.getElementById('btn') == event.currentTarget;
console.log(el.innerHTML);
}
}
})
</script>
// 三種寫法
1. DOM 事件 click 上卷拘,不加()喊废,methods 方法中 click,可加可不加 event栗弟;
2. DOM 事件 click 上污筷,加(),methods 方法中 click乍赫,不能加 event瓣蛀;
3. DOM 事件 click 上,加($event)雷厂,并傳入 $event惋增,methods 方法中 click,可加可不加 event改鲫;
19. nextTick的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>nextTick</title>
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<p ref="txt" id="p1" v-if="show">{{message}}</p>
<p>{{msg}}</p>
<button @click="getTxt">點擊</button>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
show: true,
message: '原文本',
msg: ''
},
methods: {
getTxt () {
this.show = true;
// 箭頭函數(shù)寫法
this.$nextTick(() => {
console.log(this.$refs.txt); // <p id="p1">原文本</p>
console.log(document.getElementById('p1')); // <p id="p1">原文本</p>
this.msg = this.$refs.txt.innerHTML +' + '+ '新文本內(nèi)容';
console.log('原文本內(nèi)容:', this.$refs.txt.innerHTML);
})
// this異步綁定 .bind(this)
// this.$nextTick().then(function() {
// this.msg = this.$refs.txt.innerHTML +' + '+ '新文本內(nèi)容';
// console.log('原始文本內(nèi)容:', this.$refs.txt.innerHTML);
// }.bind(this));
}
}
})
</script>
</html>
解析:使用v-show進行顯示隱藏诈皿,methods里面是直接可以獲取到文本值,如果用v-if像棘,是不能獲取的文本值的稽亏。
this.$nextTick的作用是在下次dom更新循環(huán)完成之后進行調(diào)用
ref 被用來給元素或子組件注冊引用信息。引用信息將會注冊在父組件的 $refs 對象上缕题。
元素上綁定 ref (eg: ref='txt') 屬性措左,獲取該元素使用 this.$refs.txt 即可。也可使用事件(event)獲取當前元素(var el = event.currentTarget)避除。
20. vue中 keep-alive 組件的作用
<!-- App.vue -->
<template>
<div id="app">
<router-link to="/home">主頁</router-link>
<router-link to="/news">新聞</router-link>
<keep-alive include="keep_alive">
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
include: "keep_alive"
}
}
}
</script>
<!-- 哪個組件需要緩存 該組件 name 就需要綁定App.vue的 include 屬性,并在 routes 上綁定 meta: { keepAlive: true } -->
<!-- // true表示需要使用緩存 false表示不需要被緩存 -->
<!-- Home.vue -->
<template>
<div id="home">
<input type="text" placeholder="" name="">
</div>
</template>
<script>
export default {
// 此時綁定的 name 是 App.vue 的 include 屬性值
name: 'keep_alive',
data() {
return {}
}
}
</script>
<!-- News.vue -->
<template>
<div id="news">
<input placeholder="輸入框"></input>
</div>
</template>
<script>
export default {
// 同 Home
name: 'keep_alive',
data() {
return {}
}
}
</script>
<style scoped>
</style>
<!-- router/index.js -->
<script>
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
var routes = [
{
path: '/',
component: Home
},
{
path: '/home',
name: 'Home',
component: Home,
meta: {
keepAlive: true // true表示需要使用緩存 false表示不需要被緩存
}
},
{
path: '/news',
name: 'News',
component: News,
meta: {
keepAlive: true
}
}
]
export default new Router({routes})
</script>
說明:
(1) 在Home頁面輸入框輸入“home”胸嘁,然后通過路由跳轉到News頁面瓶摆;
(2) 回到Home頁面發(fā)現(xiàn) input 之前輸入的"home"依然保留,說明頁面信息成功保存在內(nèi)存中性宏;
keep-alive的作用:keep-alive 是Vue的內(nèi)置組件群井,能在組件切換過程中將狀態(tài)保留在內(nèi)存中,防止重復渲染DOM毫胜。
keep-alive的屬性:
include: 字符串或正則表達式书斜。只有匹配的組件會被緩存诬辈。
exclude: 字符串或正則表達式。任何匹配的組件都不會被緩存荐吉。
21. vue等單頁面應用及其優(yōu)缺點
優(yōu)點:
Vue 的目標是通過盡可能簡單的 API 實現(xiàn)響應的數(shù)據(jù)綁定和組合的視圖組件焙糟,核心是一個響應的數(shù)據(jù)綁定系統(tǒng)。MVVM样屠、數(shù)據(jù)驅動穿撮、組件化、輕量痪欲、簡潔悦穿、高效、快速业踢、模塊友好栗柒。
1、具有桌面應用的即時性知举、網(wǎng)站的可移植性和可訪問性瞬沦。
2、用戶體驗好负蠕、快,內(nèi)容的改變不需要重新加載整個頁面。
3屡江、基于上面一點赛不,SPA相對對服務器壓力小文黎。
4、良好的前后端分離。SPA和RESTful架構一起使用业汰,后端不再負責模板渲染、輸出頁面工作氛濒,web前端和各種移動終端地位對等窿冯,后端API通用化。
5仰挣、同一套后端程序代碼洲愤,不用修改就可以用于Web界面、手機州藕、平板等多種客戶端;
缺點:
不支持低版本的瀏覽器馅精,最低只支持到IE9茄蚯;
不利于SEO的優(yōu)化(如果要支持SEO,建議通過服務端來進行渲染組件);
第一次加載首頁耗時相對長一些;
不可以使用瀏覽器的導航按鈕都办,需自行實現(xiàn)前進、后退歼培。
22. vue中子組件調(diào)用父組件的方法
Vue中子組件調(diào)用父組件的方法震蒋,這里有三種方法提供參考
第一種方法是直接在子組件中通過this.$parent.event來調(diào)用父組件的方法
<!-- App.vue -->
<template>
<div id="app">
<Child />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('測試');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">點擊</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子組件child'
}
},
methods: {
childMethod() {
this.$parent.fatherMethod()
}
}
}
</script>
第二種方法是在子組件里用$emit向父組件觸發(fā)一個事件查剖,父組件監(jiān)聽這個事件就行了菌仁。
<!-- App.vue -->
<template>
<div id="app">
<Child @fatherMethod="fatherMethod" />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('測試');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">點擊</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子組件child'
}
},
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
}
</script>
第三種是父組件把方法傳入子組件中峡碉,在子組件里直接調(diào)用這個方法
<!-- App.vue -->
<template>
<div id="app">
<Child :fatherMethod="fatherMethod" />
</div>
</template>
<script>
import Child from '@/components/Child'
export default {
name: 'App',
components: {
Child
},
methods: {
fatherMethod() {
console.log('測試');
}
}
</script>
<!-- Child.vue -->
<template>
<div id="child">
<button @click="childMethod()">點擊</button>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
msg: '子組件child'
}
},
props: {
fatherMethod: Function,
default: null
},
methods: {
childMethod() {
if (this.fatherMethod){
this.fatherMethod();
}
}
}
}
</script>
23. package.json的文件解析
name:項目名稱
version:項目版本號
description:描述信息,有助于搜索
scripts:支持的腳本头岔,默認是一個空的 test
private:公有私有
keywords:關鍵字塔拳,有助于在人們使用 npm search 搜索時發(fā)現(xiàn)你的項目
author:作者信息
license:證書信息(默認是 MIT)
dependencies:在生產(chǎn)環(huán)境中需要用到的依賴
devDependencies:在開發(fā)環(huán)境中用到的依賴,上線打包后的代碼是不存在的
engines:node和npm的版本要求
browserslist:瀏覽器要求
24. vue 全局變量和函數(shù)的使用
- 首先在src下創(chuàng)建global文件夾峡竣,創(chuàng)建global_data.js
const url = 'http://www.baicu.com'
const name = 'zhangsan'
// 暴露變量
export default {
url,
name
}
//或者
// module.exports = {
// url,
// name
// }
- 引用(局部引用靠抑,全局引用)
// 全局變量的局部全局引入
// App.vue引用 哪個頁面需要哪個頁面引入(局部)
import GLOBAL from '@/global/global_data'
export default {
name: 'App',
data() {
return {
url: GLOBAL.url,
}
}
}
// main.js 引入 (全局)
import globalData from '@/global/global_data'
// 掛載vue原型
Vue.prototype.GLOBAL = globalData
// App.vue 使用
export default {
name: 'App',
data() {
return {
url: this.GLOBAL.url,
}
}
}
// 全局函數(shù)的引入
// 第一種方法
// main.js 直接綁定
Vue.prototype.global_fun1 = function() {
return console.log('fun1');
}
// App.vue 頁面輸出
export default {
name: 'App',
mounted() {
this.global_fun1(); // 打印 fun1
}
}
// 第二種方法
// global/新建global_fun.js
import Vue from 'vue'
function fun11(params){
console.log(params);
}
export default {
Vue.prototype.global_fun11 = (params) => fun11(params);
}
// next main.js 引入
import globalFun from '@/global/global_fun'
Vue.use(globalFun);
// App.vue 使用
export default {
name: 'App',
mounted() {
this.global_fun11('zhangsan'); // 打印 zhangsan
}
}
25. vue彈出窗口之后禁止頁面滑動
先阻止默認時間,然后給body添加overflow:hidden;
export default {
methods: {
stop() {
var stop = function(event) {
event.preventDefault();
}
document.body.style.overflow = 'hidden';
document.addEventListener('touchmove', stop, false); // 禁止頁面滑動
}
move() {
var move = function(event) {
event.preventDefault();
};
document.body.style.overflow = ''; //出現(xiàn)滾動條
document.removeEventListener("touchmove", move, false); //開啟頁面滑動
}
}
}
26. v-for產(chǎn)生的列表适掰,實現(xiàn)active的切換颂碧?
<template>
<ul>
<li v-for="(item, index) in movieArr" @click="curIndex = index" :class="{actived: index == curIndex}">
<span>{{item}}</span>
</li>
</ul>
</template>
<script>
export default {
name: 'App',
data() {
curIndex: 0,
movieArr: ['三國', '大人物', '無雙']
}
}
</script>
<style>
.actived {
color: red;
}
</style>
27. vue實現(xiàn)路由懶加載
懶加載:也叫延遲加載,即在需要的時候進行加載类浪,隨用隨載载城。
為什么需要使用懶加載?
像vue這種單頁面應用费就,如果不應用懶加載诉瓦,運用 webpack 打包后的文件將會異常的大,造成進入首頁時力细,需要加載的內(nèi)容過多睬澡,時間過長,會出現(xiàn)長時間的白屏眠蚂,即使做了loading也是不利于用戶體驗煞聪,而運用懶加載則可以將頁面進行劃分,需要的時候加載頁面逝慧,可以有效的分擔首頁所承擔的加載壓力昔脯,減少首頁加載用時
不使用懶加載的路由配置:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from '@/components/Home'
import News from '@/components/News'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Home
},
{
path: '/helloworld',
name: 'HelloWorld',
component: HelloWorld,
meta: {
keepAlive: true
}
},
{
path: '/home',
name: 'Home',
component: Home,
// 組件切換時啄糙,將狀態(tài)保存在內(nèi)存中,防止重復渲染
meta: {
keepAlive: true // true表示需要使用緩存 false表示不需要被緩存
}
},
{
path: '/news',
name: 'News',
component: News,
meta: {
keepAlive: true
}
}
]
})
使用懶加載的路由配置:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
},
{
path: '/helloworld',
name: 'HelloWorld',
component: resolve => require(['@/components/HelloWorld'], resolve)
},
{
path: '/home',
name: 'Home',
component: resolve => require(['@/components/Home'], resolve),
children: [{
path: '/detail',
name: 'Detail',
component: resolve => require(['@/components/Detail'], resolve)
}],
meta: {
keepAlive: true
}
},
{
path: '/news',
name: 'News',
component: resolve => require(['@/components/News'], resolve),
meta: {
keepAlive: true
}
}
]
})
28. vue-router 的兩種模式
hash 模式 和 history 模式
hash 模式:
hash 發(fā)生變化之后云稚,url 都會被瀏覽器記錄下來迈套,所以你會發(fā)現(xiàn)瀏覽器的前進后退都可以用了,點擊前進碱鳞、后退,可以跳轉頁面踱蛀。
hash模式的工作原理是onhashchange事件窿给,可以在window監(jiān)聽hash的變化。
event 事件里邊有兩個屬性newURL和oldURL率拒”琅荩可以通過模擬改變 hash 的值,動態(tài)改變頁面數(shù)據(jù)猬膨。
// 頁面的URL:http://kuayu.lc/hash.html#pink角撞,通過改變 hash 的顏色值,來改變 div 的顏色勃痴。
<div id="div1" style="height: 500px;width: 500px;margin: 0 auto"></div>
<script>
window.onhashchange = function(event){
let event = event || window.event;
let hash = location.hash.slice(1);
document.getElementById('div1').style.backgroundColor = hash
}
</script>
盡管瀏覽器沒有向服務器發(fā)送請求谒所,但頁面狀態(tài)已經(jīng)和 url 關聯(lián)起來了,這就是所謂的前端路由沛申,單頁應用的標配劣领。
網(wǎng)易云音樂,百度網(wǎng)盤就采用了hash路由铁材,看起來就是這個樣子:
- 網(wǎng)易云音樂:http://music.163.com/#/friend
- 百度網(wǎng)盤:https://pan.baidu.com/disk/home#list/vmode=list
history模式:
把window.history 對象打印出來之后尖淘,可以看到里邊提供的方法和記錄長度(__ proto__ 原型鏈上)
console.log(window.history);
前進,后退著觉,跳轉操作方法:
history.go(-2); //后退2次
history.go(2); //前進2次
history.go(0); //刷新當前頁面
history.back(); //后退
history.forward(); //前進
如果不想用 # 的 hash村生,我們可以用路由的 history 模式。
export default new VueRouter({
mode: 'history',
routes: [...]
})
當你使用 history 模式時饼丘,URL 就像正常的 url : http://localhost:8080/news
不過這種模式要玩好的話趁桃,還需要后臺配置支持。因為我們的應用是個單頁客戶端應用葬毫,如果后臺沒有正確的配置镇辉,當用戶在瀏覽器直接訪問 http://localhost:8080/news1234 (沒有路由,訪問不到的情況) 就會返回 404贴捡,這就不好看了忽肛。
為了避免這種情況,你應該在 Vue 應用里面覆蓋所有的路由情況烂斋,然后在給出一個 404 的組件頁面屹逛。
export default {
mode: 'history',
routes: [
{path: '*', component: resolve => require(['@/components/NotFound'], resolve)}
]
}
29. $router 和 $route 的區(qū)別
$router 為 VueRouter 實例础废,想要導航到不同 URL,使用 $router.push 方法罕模。
$route 為當前 router 跳轉對象评腺,里面可以獲取 name 、 path 淑掌、 query 蒿讥、 params、meta 等信息抛腕。