面试官问:你用过vue-cli吗?说一说
回答:好的
vue-cli安装,第一用npm安装
npm -v
vue-cli安装
npm install vue-cli -g
vue -V
-g代表全局安装,然后查看版本
初始化项目
用vue init命令来初始化项目
vue init <template-name> <project-name>
init:表示要用vue-cli来初始化项目
<template-name>:表示模板名称
vue-cli官方提供的5种模板
webpack
webpack-simple
browserify
browserify-simple
simple
<project-name>:标识项目名称,用户根据自己的项目来起名字。
项目初始化
vue init webpack my-vue-demo
Project name:项目名称
Project description:项目描述
Author:作者
Install vue-router? 是否安装vue的路由插件,需要安装,选择Y
Use ESLint to lint your code? 是否用ESLint来限制你的代码错误和风格。不需要输入n,需要选择y
setup unit tests with Karma + Mocha? 是否需要安装单元测试工具
Setup e2e tests with Nightwatch? 是否安装e2e来进行用户行为模拟测试
运行项目
npm run dev
npm run build
面试官问:你了解vue-router吗?说一说
安装
npm install vue-router --save
核心文件
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
// Vue全局使用Router
Vue.use(Router)
export default new Router({
routes: [ //配置路由,这里是个数组
{ //每一个链接都是一个对象
path: '/', //链接路径
name: 'HelloWorld', //路由名称,
component: HelloWorld //对应的组件模板
}
]
})
使用
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
new Vue({
el: '#app',
router, // 注入框架中
components: { App },
template: '<App/>'
})
页面跳转
<router-link to="/">[显示字段]</router-link>
<p>导航 :
<router-link to="/">首页</router-link>
<router-link to="/hello">hello</router-link>
</p>
编程式导航
this.$router.push('/xxx')
<button @click="goHome">回到首页</button>
export default {
name: 'app',
methods: {
goHome(){
this.$router.push('/home');
}
}
}
// 同于 history.back()
this.$router.go(-1)
// 同于 history.forward()
this.$router.go(1)
路由嵌套
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>导航 :
<router-link to="/home">首页</router-link> |
<router-link to="/home/one">-子页面1</router-link> |
<router-link to="/home/two">-子页面2</router-link>
</p>
<router-view/>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: 'dada!'
}
}
}
</script>
<style scoped>
</style>
子页面
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'One',
data () {
return {
msg: 'Hi, I am One Page!'
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Two',
data () {
return {
msg: 'Hi, I am Two Page!'
}
}
}
</script>
<style scoped>
</style>
路由配置
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import One from '@/components/One'
import Two from '@/components/Two'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 默认页面重定向到主页
redirect: '/home'
},
{
path: '/home', // 主页路由
name: 'Home',
component: Home,
children:[ // 嵌套子路由
{
path:'one', // 子页面1
component:One
},
{
path:'two', // 子页面2
component:Two
},
]
}
]
})
路由传递参数
<router-link :to="{name:xxx, params: {key:value}}">
dada
</router-link>
<router-link :to="{name: 'one', params:{username:'123'}}">
子页面
</router-link>
{
path:'one', // 子页面
name: 'one', // 路由名称-命名路由
component:One
}
<h2>{{$route.params.username}}</h2>
url中传递参数
{
path:'/home/two/:id/:name', // 子页面
component:Two
},
<p>ID:{{ $route.params.id}}</p>
<p>名称:{{ $route.params.name}}</p>
<router-link to="/home/two/1/">子页面</router-link>
编程式导航带参数
{
path:'/home/three', // 子页面
name: 'three',
component:Three
}
<p>ID:{{ $route.params.id}}</p>
<p>名称:{{ $route.params.name}}</p>
<button @click="toThreePage">页面-params传参</button>
// script
methods: {
toThreePage() {
this.$router.push(
{
name: 'three',
params: {
id: 1,
name: 'dada'
}
}
)
}
}
query传参数
{
path:'/home/three', // 子页面
name: 'three',
component:Three
}
<p>ID:{{ $route.query.id}}</p>
<p>名称:{{ $route.query.name}}</p>
<button @click="toThreePage">页面-params传参</button>
methods: {
toThreePage() {
this.$router.push(
{path: '/home/three', query: {id: 1, name: 'da'}}
)
}
}
命名路由
{
path: 'one', // 子页面
name: 'one', // 路由名称-命名路由
component: One // 页面组件
}
// template跳转调用
<router-link :to="{name: 'one'}">子页面</router-link>
// router.push函数跳转调用
router.push({ name: 'user'}})
import Vue from 'vue'
import Router from 'vue-router'
// 创建页面组件
const Header = { template: '<div>Header</div>' }
const Left = { template: '<div>Left</div>' }
const Right = { template: '<div>Right</div>' }
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 主页路由
components: {
default: Header,
a: Left,
b: Right
}
}
]
})
<template>
<div id="app">
<router-view />
<router-view name="a" class="left" />
<router-view name="b" class="right" />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
width: 500px;
border: 1px solid red;
margin: 0 auto;
}
.left,.right{
float: left;
width:48%;
text-align: center;
border:1px solid red
}
</style>
重定向
export default new Router({
routes: [
{
path: '/', // 默认页面重定向到主页
redirect: '/home' // 重定向
},
{
path: '/home', // 主页路由
component: Home,
children:[ // 嵌套子路由
{
path:'/home/two/:id/:name', // 子页面
component:Two
},
{
path:'/home/three/:id/:name', // 子页面
name: 'three', // 路由名称-命名路由
redirect: '/home/two/:id/:name' // 重定向-传递参数
},
]
}
]
})
<router-link to="/">首页</router-link> |
<router-link to="/home/two/1/lisi">子页面</router-link> |
<router-link :to="{name: 'three', params: {id: 1, name: 'dada'}}">
子页面
</router-link>
redirect: '/home' // 重定向-不带参数
redirect: '/home/two/:id/:name' // 重定向-传递参数
别名
{
path:'/one', // 子页面
component:One,
alias: '/oneother'
}
<router-link to="/oneother">子页面1</router-link>
.fade-enter-active { transition: opacity .5s; } .fade-enter { opacity: 0; } .fade-leave { opacity: 1; } .fade-leave-active { opacity:0; transition: opacity .5s; }
404
// 404
{
path: '*',
component: () => import('@/components/404')
}
路由钩子,第一全局钩子,第二,路由单独钩子,第三,组件内钩子
const router = new VueRouter({ ... })
// 全局路由拦截-进入页面前执行
router.beforeEach((to, from, next) => {
next();
});
router.afterEach(() => {
});
export default router;
路由单独钩子
{
path:'/home/one', // 子页面
component: One,
beforeEnter: (to, from, next) => {
console.log('进入前执行');
next();
}
}
组件内钩子
<script>
export default {
name: 'Two',
data () {
return {
msg: 'dada'
}
},
beforeRouteEnter(to, from, next) {
console.log('进入enter路由钩子')
next()
},
beforeRouteLeave(to,from, next){
console.log('进入leave路由钩子')
next()
},
beforeRouteUpdate(to, from, next) {
console.log('进入update路由钩子')
console.log(to.params.id)
next()
}
}
</script>
路由
import Home from '@/components/Home'
{
path: '/home',
component: Home
}
面试官问:你了解vuex是什么吗?要不也说说
回答:好的。
vuex是一个为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,以相应的规则保证状态以一种可预测的方式发生变化。
单向数据流
vuex的核心
安装
npm install vuex --save
使用
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 1
}
const mutations = {
DA(state, n) {
state.count += n;
}
}
const getters = {
count: function(state){
return state.count;
}
}
const actions ={
// 触发mutations中相应的方法-一般小写
add ({commit}, data) {
commit('DA', data)
}
}
const store = new Vuex.Store({
state,
mutations,
getters,
actions
});
export default store;
<h2>{{ $store.state.count }}</h2>
computed: {
count() {
return this.$store.state.count;
}
}
computed: mapState({
// es5写法
count: function (state) {
return state.count;
},
// es6写法
count: state => state.count
})
数组获取
computed: mapState(['count'])
computed: mapState({
count: 'count'
})
<button @click="$store.commit('DA')">+</button>
const mutations = {
// 状态变更函数
DA(state) {
state.count++;
}
}
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块,从上至下进行同样方式的分割。
// 模块A
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
// 模块B
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
// 组装
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
// 取值
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
面试官最后一问:你了解axios吗?
回答:嗯,用过。
Axios 是基于 promise 的 HTTP 库,用在浏览器和 node.js 中。就是前端最火最简单的一个http请求解决方案。
安装
npm install vuex --save
代码封装 import fetch from '@/util/fetch' const TMPURL = ''; // url地址 const params = {}; // 参数 fetch.post(TMPURL + '/login/login', params); import axios from 'axios'; const httpService = axios.create({ baseURL: process.env.BASE_API, // 需自定义 // 请求超时时间 timeout: 3000 }); // request拦截器 httpService.interceptors.request.use( config => { // 加入token if (true) { config.headers['User-Token'] = ''; } return config; }, error => Promise.reject(error); } ) // respone拦截器 httpService.interceptors.response.use( response => { const res = response.data; if (res.statuscode != 1) { return Promise.reject({ status: res.statuscode, message: res.message }); } else { return response.data; } }, error => { if (error && error.response) { switch (error.response.status) { case 400: error.message = '错误请求'; break; case 401: error.message = '未授权,请重新登录'; break; case 403: error.message = '拒绝访问'; break; case 404: error.message = '请求错误,未找到该资源'; break; case 405: error.message = '请求方法未允许'; break; case 408: error.message = '请求超时'; break; case 500: error.message = '服务器端出错'; break; case 501: error.message = '网络未实现'; break; case 502: error.message = '网络错误'; break; case 503: error.message = '服务不可用'; break; case 504: error.message = '网络超时'; break; case 505: error.message = 'http版本不支持该请求'; break; default: error.message = `未知错误${error.response.status}`; } } else { error.message = "连接到服务器失败"; } return Promise.reject(error); } ) /* * get请求 * url:请求地址 * params:参数 * */ export function get(url, params = {}) { return new Promise((resolve, reject) => { httpService({ url: url, method: 'get', params: params }).then(response => { resolve(response); }).catch(error => { reject(error); }); }); } /* * post请求 * url:请求地址 * params:参数 * */ export function post(url, params = {}) { return new Promise((resolve, reject) => { httpService({ url: url, method: 'post', data: params }).then(response => { resolve(response); }).catch(error => { reject(error); }); }); } /* * 文件上传 * url:请求地址 * params:参数 * */ export function fileUpload(url, params = {}) { return new Promise((resolve, reject) => { httpService({ url: url, method: 'post', data: params, headers: { 'Content-Type': 'multipart/form-data' } }).then(response => { resolve(response); }).catch(error => { reject(error); }); }); } export default { get, post, fileUpload }
————————————————
智一面|前端面试必备练习题