回答:Vue的安装可以从两个方面进行安装,第一种是CDN引入,第二种是NPM安装。
CDN引入
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
NPM安装
npm install vue
面试官问,如何创建Vue项目?
写下代码:
创建项目
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之Helloworld</title> <!--引入Vue库--> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!--创建一个Div--> <div id="app"> <!--Vue的模板的绑定数据的方法,用两对花括号进行绑定Vue中的数据对象的属性 --> {{message}} </div> <!--创建Vue的对象,并把数据绑定到上面创建好的div上去。--> <script type="text/javascript"> var app=new Vue({ // 创建Vue对象。Vue的核心对象。 el:'#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器 data:{ // data: 是Vue对象中绑定的数据 message:'hello Vue!' // message 自定义的数据 } }) </script> </body> </html>
输出的结果:
hello Vue!
面试官问:v-if和v-show的区别是?
回答:
内部指令
v-if用于显示与隐藏的元素
<div v-if="isShow">前端</div>
v-else,v-if不是它,就是它v-else
<div v-else>前端</div>
v-show
<div v-show="isShow">你好</div>
v-else-if
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>
v-if和v-show的区别是:
v-if用于元素的被销毁和重建,使用这个指令开销较为高,在运行过程中,尽量用在很少改变时的情况下使用。v-if元素销毁和存在
v-show的用法,这个指令的使用开销较小,在常频繁地切换使用
面试官问:内部指令的用法有哪些,怎么用呢?
回答:好,慢慢讲述。
v-for的用法
<!-- 模板 --> <div id="app"> <ul> <li v-for="item in items"> {{item}} </li> </ul> </div> <!--JS代码 --> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ items:[ 1, 2, 3, 4] } }) </script> 对象遍历 <!-- 模板 --> <div id="app"> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} - {{ value }} </li> </ul> </div> <!--JS代码 --> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ object: { firstName: 'dada', lastName: 'qianduan' } } }) </script> v-text的出现为了解决{{xx}}这个取值的问题,当网络很慢的情况下,或者是运行时出错的情况下,页面显示为{{xxx}}。 <div>{{ message }}</div> <!-- 一样的 --> <div v-text="message"></div> v-html指令是用于输出html代码 <span v-html="msgHtml"></span> v-on的用法 // html <div>{{count}}</div> <button v-on:click="add">加</button> // JS data:{ count: 1 }, methods: { add() { this.count++; } } 缩写 <button @click="add">加</button> v-model的用法,model都需要在data中声明初始值: data: { count: 1, } input的用法 <input type="text" v-model="message"> textarea <textarea cols="30" rows="10" v-model="message"></textarea> checkbox <input type="checkbox" id="first" value="1" v-model="status"> <label for="first">有效</label> <input type="checkbox" id="second" value="2" v-model="status"> <label for="second">无效</label> <div>状态:{{status}}</div> radio <input type="radio" id="one" value="男" v-model="sex"> <label for="one">男</label> <input type="radio" id="two" value="女" v-model="sex"> <label for="one">女</label> <div>性别:{{sex}}</div> select <select v-model="selected"> <option disabled value="">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <div>Selected: {{ selected }}</div> v-bind方法 // html <img v-bind:src="imgSrc" width="200px"> // js data: { imgSrc:'' } 缩写 <img :src="imgSrc" width="200px"> v-pre方法,用这个指令可以直接跳过vue的编译,直接输出原始值,如果在标签中加入v-pre就不会输出vue中的data值。 <div v-pre>{{message}}</div> v-cloak可以在vue渲染时指定的整个dom后才进行显示,必须和css样式一起用 // css [v-cloak] { display: none; } // html <div v-cloak>{{message}}</div> v-once只能显示一次,第一次渲染的值就不会改变了
<div v-once>{{message}}</div>
面试官问:你知道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) { return value.toUpperCase(); } } mixins用于减少代码污染,减少代码量,实现代码重用 var addLog={ updated:function(){ console.log("数据放生变化,变化成"+this.count+"."); } } var app = new Vue({ el:'#app', data:{ count: 100 }, // 混入 mixins: [addLog] }) extends用于扩展,对构造器进行扩展 var extendObj ={ created: function(){ console.log("我是"); } } var app = new Vue({ el:'#app', data:{ }, // 扩展 extends: extendObj }) 面试官问,你知道哪些实例事件吗? 回答,vue有实例属性,实例方法,实例事件 $on接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法 app.$on('reduce',function(){ console.log('执行了reduce()'); this.count--; }); app.$once('reduceOnce',function(){ console.log('只执行一次的方法'); this.count--; }); function off(){ console.log('关闭事件'); app.$off('reduce'); } function reduce() { // 事件调用 console.log('emit事件调用'); app.$emit('reduce'); } 面试官问:你知道自定义指令吗 回答:知道吧 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之自定义指令</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <div v-test="color"> {{num}} </div> </div> <button onclick="unbindApp()">解绑</button> <script type="text/javascript"> 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' } }) </script> </body> </html> 面试官问:你用过组件吗? 回答,用过的 组件全局注册 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">全局组件: {{ count }}</button>' }); new Vue({ el: '#app' }); <button-counter></button-counter> 组件局部注册 new Vue({ el: '#app', components:{ "button-inner":{ data: function() { return { inner: 0 } }, template: '<button v-on:click="inner++">局部组件: {{ inner }}</button>' } } }); <button-inner></button-inner> props属性传值 new Vue({ el: '#app', components:{ "button-props":{ template:` <div style="color:red;"> 参数1: {{ da }}:---参数2: {{fromHere}} </div> `, props:['da', 'fromHere'] } } }); // html使用 <button-props da="da" from-here="world"></button-props> props中需要驼峰取值 父子组件 // 子组件 var city = { template:`<div>dada</div>` } // 父组件 var parent = { template: `<div> <p> dadada!</p> <city></city> </div>`, components:{ "city": city } } // 实例化 new Vue({ el: '#app', // 定义局部组件 components:{ // 组件注册 "parent": parent } }); // html使用 <parent></parent> 面试官:你了解模板吗? 回答:还好 <div id="app"> </div> <script type="text/javascript"> // 实例化 new Vue({ el: '#app', data: { message: 'hello' }, template:`<h1 style="color:red">模板</h1>` }); </script> <div id="app"> <template id="demo2"> <h2 style="color:red">template模板</h2> </template> </div> <script type="text/javascript"> // 实例化 new Vue({ el: '#app', data: { message: 'hello' }, template:'#demo2' }); </script> <div id="app"> </div> <script type="x-template" id="demo3"> <h2 style="color:red">script标签模板</h2> </script> <script type="text/javascript"> // 实例化 new Vue({ el: '#app', data: { message: 'hello' }, template:'#demo3' }); </script> 面试问:你了解插槽不? 回答:插槽就是slot,是组件的一块Hmtl模板 <div id="app"> <children> <span>123</span> </children> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', components: { children: { template: "<button><slot></slot>单个插槽</button>" } } }); </script> 具名插槽slot,具名插槽可以在一个组件中出现n次 <div id="app"> <children> <span slot="first" @click="toknow">123</span> <span slot="second">456</span> </children> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', methods: { toknow: function () { console.log("dada"); } }, components: { children: { template: "<button> <slot name='first'> </slot> 具名插槽 <slot name='second'> </slot> </button>" } } }); </script> 作用域插槽slot <div id="app"> <!-- 将数据传递给组件 --> <tb-list :data="data"> <template slot-scope="scope"> <p>索引:{{JSON.stringify(scope)}}</p> <p>索引:{{scope.$index}}</p> <p>姓名:{{scope.row.name}}</p> <p>年龄: {{scope.row.age}}</p> <p>性别: {{scope.row.sex}}</p> </template> </tb-list> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { data: [{ name: 'dada', age: '12', sex: 'man' }] }, components: { // 作用域slot 'tb-list': { template: `<ul> <li v-for="(item, index) in data"> <slot :row="item" :$index="index"> </slot> </li> </ul>`, // 获取值 props: ['data'] } } }); </script>
————————————————
智一面|前端面试必备练习题