(给达达前端加星标,提升前端技能)
面试官问:Vue如何安装的呢?
达达回答:Vue的安装可以从两个方面进行安装,第一种是CDN引入,第二种是NPM安装。
CDN引入
NPM安装
npm install vue
面试官问,如何创建Vue项目?
达达写下代码:
创建项目
{{message}}
var app=new Vue({ // 创建Vue对象。Vue的核心对象。
el:'#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器
data:{ // data: 是Vue对象中绑定的数据
message:'hello Vue!' // message 自定义的数据
}
})
输出的结果:
hello Vue!
面试官问:v-if和v-show的区别是?
达达回答:
内部指令
v-if用于显示与隐藏的元素
v-else,v-if不是它,就是它v-else
v-show
v-else-if
v-if和v-show的区别是:
v-if用于元素的被销毁和重建,使用这个指令开销较为高,在运行过程中,尽量用在很少改变时的情况下使用。v-if元素销毁和存在
v-show的用法,这个指令的使用开销较小,在常频繁地切换使用
面试官问:内部指令的用法有哪些,怎么用呢?
达达回答:好,慢慢讲述。
v-for的用法
-
{{item}}
var app=new Vue({
el:'#app',
data:{
items:[ 1, 2, 3, 4]
}
})
对象遍历
-
{{ index }}. {{ key }} - {{ value }}
var app=new Vue({
el:'#app',
data:{
object: {
firstName: 'dada',
lastName: 'qianduan'
}
}
})
v-text的出现为了解决{{xx}}这个取值的问题,当网络很慢的情况下,或者是运行时出错的情况下,页面显示为{{xxx}}。
v-html指令是用于输出html代码
v-on的用法
// html
缩写
加
v-model的用法,model都需要在data中声明初始值:
data: {count:1,}
input的用法
textarea
checkbox
radio
select
v-bind方法
// html
// js
data: {
imgSrc:''
}
缩写
v-pre方法,用这个指令可以直接跳过vue的编译,直接输出原始值,如果在标签中加入v-pre就不会输出vue中的data值。
v-cloak可以在vue渲染时指定的整个dom后才进行显示,必须和css样式一起用
// css[v-cloak] { display: none;}// html
v-once只能显示一次,第一次渲染的值就不会改变了
面试官问:你知道Vue生命周期吗?
达达回答:
new Vue() 实例化对象,init events & lifecycle 初始化,事件和生命周期
beforeCreate组件实例刚被创建,还没有实例化之前,执行一些初始化的操作,可以制作加载动画
init injections & reactivity 初始化,依赖注入和校验
created组件实例创建完成,属性已经绑定,但是dom还没有生成,$el属性还不存在,页面未被展示,结束加载动画,发起异步网络请求
has"el" option? no 判断是否存在el属性,如果有,则继续编译,如果没有,则停止编译,生命周期结束,知道在该vue实例上调用vm.$mount(el),即被唤醒继续执行编译,如果注释掉“el”,等程序到create就停止了
判断是否有template,如果有,则将其编译成render函数,如果没有,则将外部的HTML作为模板编译,template中的模板优先级高于outer html 的优先级。
yes的路线,compile template into render function
如果tremplate中组件的话,执行render方法渲染组件内容
compile el's outerhtml as template
beforeMount,完成虚拟dom配置,模板已经被编译,把data里面的数据和模板生成html,此时还没有挂载html到页面上
create vm.$el and replace "el" with it,给vue实例对象添加$el成员,并且替换掉挂载的dom元素
mounted,用上面编译好的html内容替换el属性指向dom对象,方法结束后,dom结构完成,页面显示出来,发起网络请求
Mounted,when data changes,beforeUpdate,当vue发现data中的数据发生了改变,会触发对应组件的重新渲染,一般在组件发生更新之前,调用这个函数,页面还不会展示修改的内容,但虚拟dom已经配置修改
virtual dom re-render and patch,重新渲染虚拟dom并通过diff算法对比vonde节点差异更新真实dom,updated,组件更新后,此方法执行后,修改后的页面展现出来,即为view重新渲染,数据更新
when wm.$destroy() is called,beforeDestroy,组件实例销毁前调用,实例仍然完全可用
teardown watchers, child components and event listeners 拆卸观察者,子组件,事件监听者
destroyed,在vue实例销毁后调用,实例指示的所有东西都会被解除绑定,所有的事件监听都会被移除,所有的子实例都会被销毁
面试官问:在vue中常用的语句有哪些
达达回答:好的,请认真听讲
computed计算属性,用于对原数据进行修改
computed: {
newPrice () {
return '¥' + this.price + '元';
}
}
methods方法属性,用于绑定方法
methods:{add(num) {this.count += num; }}
watch数据变化监听器
watch: {
question(val, oldVal) {
console.log('new: %s, old: %s', val, oldVal);
}
}
filters 过滤器
filters: { filterA(value) {returnvalue.toUpperCase(); }}
mixins用于减少代码污染,减少代码量,实现代码重用
varaddLog={updated:function(){console.log("数据放生变化,变化成"+this.count+"."); }}varapp =newVue({el:'#app',data:{count:100},// 混入mixins: [addLog]})
extends用于扩展,对构造器进行扩展
varextendObj ={created:function(){console.log("我是"); }}varapp =newVue({el:'#app',data:{ },// 扩展extends: extendObj})
面试官问,你知道哪些实例事件吗?
达达回答,vue有实例属性,实例方法,实例事件
$on接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法app.$on('reduce',function(){ console.log('执行了reduce()'); this.count--;});app.$once('reduceOnce',function(){ console.log('只执行一次的方法'); this.count--;});functionoff(){ console.log('关闭事件'); app.$off('reduce');}functionreduce() { // 事件调用 console.log('emit事件调用'); app.$emit('reduce');}
面试官问:你知道自定义指令吗
达达回答:知道吧
{{num}}
function unbindApp() {
app.$destroy();
}
// 自定义指令
Vue.directive("test",{
//被绑定
bind:function (el, binding, vnode) {
console.log("1-bind 被绑定");
console.log("el:",el);
console.log("binding:",binding);
console.log("vnode:",vnode);
el.style.color = binding.value;
},
//被插入
inserted:function (el, binding, vnode) {
console.log("2-inserted 被插入");
},
//更新
update:function (el, binding, vnode) {
console.log("3-update 更新");
},
//更新完成
componentUpdated:function (el, binding, vnode) {
console.log("4-componentUpdated 更新完成");
},
//解绑
unbind:function (el, binding, vnode) {
console.log("5-unbind 解绑");
}
});
var app = new Vue({
el:'#app',
data:{
num: 123,
color:'red'
}
})
面试官问:你用过组件吗?
达达回答,用过的
组件全局注册
Vue.component('button-counter', {data:function(){return{count:0} },template:''});newVue({el:'#app'});
组件局部注册
newVue({el:'#app',components:{"button-inner":{data:function(){return{inner:0} },template:''} }});
props属性传值
newVue({el:'#app',components:{"button-props":{template:`
参数1: {{ da }}:---参数2:
{{fromHere}}
`,props:['da','fromHere'] } } });// html使用props中需要驼峰取值
父子组件
// 子组件varcity = { template:`
dadada!
面试官:你了解模板吗?
达达回答:还好
// 实例化
new Vue({
el: '#app',
data: {
message: 'hello'
},
template:`
模板
`});
template模板
// 实例化
new Vue({
el: '#app',
data: {
message: 'hello'
},
template:'#demo2'
});
script标签模板
// 实例化
new Vue({
el: '#app',
data: {
message: 'hello'
},
template:'#demo3'
});
面试问:你了解插槽不?
达达回答:插槽就是slot,是组件的一块Hmtl模板
123
var app = new Vue({
el: '#app',
components: {
children: {
template: ""
}
}
});
具名插槽slot,具名插槽可以在一个组件中出现n次
123
456
var app = new Vue({
el: '#app',
methods: {
toknow: function () {
console.log("dada");
}
},
components: {
children: {
template: "
具名插槽
"
}
}
});
作用域插槽slot
索引:{{JSON.stringify(scope)}}
索引:{{scope.$index}}
姓名:{{scope.row.name}}
年龄: {{scope.row.age}}
性别: {{scope.row.sex}}
var app = new Vue({
el: '#app',
data: {
data: [{
name: 'dada',
age: '12',
sex: 'man'
}]
},
components: {
// 作用域slot
'tb-list': {
template:
`
// 获取值
props: ['data']
}
}
});
面试官问:你用过vue-cli吗?说一说
达达回答:好的
vue-cli安装,第一用npm安装
npm -v
vue-cli安装
npm install vue-cli -g
vue -V
-g代表全局安装,然后查看版本
初始化项目
用vue init命令来初始化项目
vue init
init:表示要用vue-cli来初始化项目
vue-cli官方提供的5种模板
webpack
webpack-simple
browserify
browserify-simple
simple
项目初始化
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吗?说一说
达达回答,嗯,了解。
安装
npminstallvue-router--save
核心文件
importVuefrom'vue'importRouterfrom'vue-router'importHelloWorldfrom'@/components/HelloWorld'// Vue全局使用RouterVue.use(Router)exportdefaultnewRouter({routes: [//配置路由,这里是个数组{//每一个链接都是一个对象path:'/',//链接路径name:'HelloWorld',//路由名称,component: HelloWorld//对应的组件模板} ]})
使用
importVuefrom'vue'importAppfrom'./App'importrouterfrom'./router'Vue.config.productionTip =falsenewVue({el:'#app', router,// 注入框架中components: { App },template:'
页面跳转
导航 :
编程式导航
this.$router.push('/xxx')
export default {
name: 'app',
methods: {
goHome(){
this.$router.push('/home');
}
}
}
// 同于 history.back()
this.$router.go(-1)
// 同于 history.forward()
this.$router.go(1)
路由嵌套
{{ msg }}
导航 :
export default {
name: 'Home',
data () {
return {
msg: 'dada!'
}
}
}
子页面
{{ msg }}
export default {
name: 'One',
data () {
return {
msg: 'Hi, I am One Page!'
}
}
}
{{ msg }}
export default {
name: 'Two',
data () {
return {
msg: 'Hi, I am Two Page!'
}
}
}
路由配置
importVuefrom'vue'importRouterfrom'vue-router'importHomefrom'@/components/Home'importOnefrom'@/components/One'importTwofrom'@/components/Two'Vue.use(Router)exportdefaultnewRouter({routes: [ {path:'/',// 默认页面重定向到主页redirect:'/home'}, {path:'/home',// 主页路由name:'Home',component: Home,children:[// 嵌套子路由{path:'one',// 子页面1component:One }, {path:'two',// 子页面2component:Two }, ] } ]})
路由传递参数
dada
子页面
{path:'one', // 子页面 name:'one', // 路由名称-命名路由 component:One}
{{$route.params.username}}
url中传递参数
{path:'/home/two/:id/:name', // 子页面 component:Two},
ID:{{ $route.params.id}}
名称:{{ $route.params.name}}
编程式导航带参数
{path:'/home/three', // 子页面 name:'three', component:Three}
ID:{{ $route.params.id}}
名称:{{ $route.params.name}}
页面-params传参// scriptmethods: { toThreePage() {this.$router.push( { name:'three',params: { id:1, name:'dada'} } ) }}
query传参数
{path:'/home/three', // 子页面 name:'three', component:Three}
ID:{{ $route.query.id}}
名称:{{ $route.query.name}}
methods: {
toThreePage() {
this.$router.push(
{path: '/home/three', query: {id: 1, name: 'da'}}
)
}
}
命名路由
{path:'one', // 子页面 name:'one', // 路由名称-命名路由 component: One // 页面组件}
// template跳转调用子页面// router.push函数跳转调用router.push({ name:'user'}})
import Vue from 'vue'
import Router from 'vue-router'
// 创建页面组件
const Header = { template: '
const Left = { template: '
const Right = { template: '
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 主页路由
components: {
default: Header,
a: Left,
b: Right
}
}
]
})
export default {
name: 'App'
}
#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
}
重定向
exportdefaultnewRouter({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'// 重定向-传递参数 }, ] } ]})
子页面
redirect:'/home'// 重定向-不带参数
redirect:'/home/two/:id/:name'// 重定向-传递参数
别名
{path:'/one', // 子页面 component:One, alias:'/oneother'}
过渡动画
.fade-enter-active{transition: opacity .5s;}.fade-enter{opacity:0;}.fade-leave{opacity:1;}.fade-leave-active{opacity:0;transition: opacity .5s;}
mode模式
exportdefaultnewRouter({mode:'history',//mode模式routes: [...]})
404
// 404{path:'*',component:()=>import('@/components/404')}
路由钩子,第一全局钩子,第二,路由单独钩子,第三,组件内钩子
constrouter =newVueRouter({ ... })// 全局路由拦截-进入页面前执行router.beforeEach((to,from, next) =>{ next();});router.afterEach(()=>{ });exportdefaultrouter;
路由单独钩子
{path:'/home/one',// 子页面component: One,beforeEnter:(to,from, next) =>{console.log('进入前执行'); next(); }}
组件内钩子
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()
}
}
路由
importHomefrom'@/components/Home'{path:'/home',component: Home}
面试官问:你了解vuex是什么吗?要不也说说
达达回答:好的。
vuex是一个为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,以相应的规则保证状态以一种可预测的方式发生变化。
单向数据流
vuex的核心
安装
npminstallvuex--save
使用
importVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)conststate = {count:1}constmutations = { DA(state, n) { state.count += n; }}constgetters = {count:function(state){returnstate.count; }}constactions ={// 触发mutations中相应的方法-一般小写add ({commit}, data) { commit('DA', data) }}conststore =newVuex.Store({ state, mutations, getters, actions});exportdefaultstore;
{{ $store.state.count }}
computed: {
count() {
return this.$store.state.count;
}
}
computed: mapState({// es5写法count:function(state){returnstate.count; },// es6写法count:state=>state.count})
数组获取computed: mapState(['count'])
computed:mapState({count:'count'})
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请求解决方案。
安装
npminstallvuex--save
代码封装
import fetchfrom'@/util/fetch'constTMPURL ='';// url地址constparams= {};// 参数fetch.post(TMPURL +'/login/login',params);
importaxiosfrom'axios';consthttpService = axios.create({baseURL: process.env.BASE_API,// 需自定义// 请求超时时间timeout:3000});// request拦截器httpService.interceptors.request.use(config=>{// 加入tokenif(true) { config.headers['User-Token'] =''; }returnconfig; }, error =>Promise.reject(error); })// respone拦截器httpService.interceptors.response.use(response=>{constres = response.data;if(res.statuscode !=1) {returnPromise.reject({status: res.statuscode,message: res.message }); }else{returnresponse.data; } }, error => {if(error && error.response) {switch(error.response.status) {case400: error.message ='错误请求';break;case401: error.message ='未授权,请重新登录';break;case403: error.message ='拒绝访问';break;case404: error.message ='请求错误,未找到该资源';break;case405: error.message ='请求方法未允许';break;case408: error.message ='请求超时';break;case500: error.message ='服务器端出错';break;case501: error.message ='网络未实现';break;case502: error.message ='网络错误';break;case503: error.message ='服务不可用';break;case504: error.message ='网络超时';break;case505: error.message ='http版本不支持该请求';break;default: error.message =`未知错误${error.response.status}`; } }else{ error.message ="连接到服务器失败"; }returnPromise.reject(error); })/*
* get请求
* url:请求地址
* params:参数
* */exportfunctionget(url, params = {}){returnnewPromise((resolve, reject) =>{ httpService({url: url,method:'get',params: params }).then(response=>{ resolve(response); }).catch(error=>{ reject(error); }); });}/*
* post请求
* url:请求地址
* params:参数
* */exportfunctionpost(url, params = {}){returnnewPromise((resolve, reject) =>{ httpService({url: url,method:'post',data: params }).then(response=>{ resolve(response); }).catch(error=>{ reject(error); }); });}/*
* 文件上传
* url:请求地址
* params:参数
* */exportfunctionfileUpload(url, params = {}){returnnewPromise((resolve, reject) =>{ httpService({url: url,method:'post',data: params,headers: {'Content-Type':'multipart/form-data'} }).then(response=>{ resolve(response); }).catch(error=>{ reject(error); }); });}exportdefault{ get, post, fileUpload}
推荐系列
推荐阅读 点击标题可跳转
【面试Vue全家桶】vue前端交互模式-es7的语法结构?async/await
【面试需要-Vue全家桶】一文带你看透Vue前端路由
【面试需要】掌握JavaScript中的this,call,apply的原理
2019年的每一天日更只为等待她的出现,好好过余生,庆余年 | 掘金年度征文
进来就是一家人【达达前端技术社群⑥】
觉得本文对你有帮助?请分享给更多人
关注「达达前端」加星标,提升前端技能
在博客平台里,未来的路还很长,也希望自己以后的文章大家能多多支持,多多批评指正,我们一起进步,一起走花路。
非常感谢读者能看到这里,如果这个文章写得还不错,觉得「达达」我有点东西的话,觉得我能够坚持的学习,觉得此人可以交朋友的话,求点赞,求关注,求分享,对暖男我来说真的
非常有用!!!
感谢阅读,原创不易,喜欢就点个[在看] or [转发朋友圈],这是我写作最大的动力。
意见反馈
若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。
这是一个有质量,有态度的公众号
点关注,有好运
好文章,我在看❤️