Vue 学习笔记
Vue:用于构建用户界面的渐进式框架。
优点:
双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单;
组件化:保留了 react 的优点,实现了 html 的封装和重用,在构建单页面应用方面有着独特的优势;
虚拟DOM:通过页面挂载完成。dom 操作是非常耗费性能的, 不再使用原生的 dom 操作节点,极大解放 dom 操作,但具体操作的还是 dom 不过是换了另一种方式。
Vue的响应式
底层是通过 object.defineProperty 实现的,在中间做了监听的机制,订阅发布者模式,结合他的一个 dep 更新的机制去实现的。
MVVM
一种架构设计,vue 和 model 之间是双向数据传递,数据改变视图就可以改变。
数据在 data 里面定义,不然是非响应式的。或者可以通过 vue 的语法糖 $set 把它强制变成响应式的。
新建一个项目:
准备:安装node.js、npm
使用国内淘宝镜像:npm install -g cnpm --registry=https://registry.npm.taobao.org
安装vue:npm install -g @vue/cli
新建项目:vue init webpack test
进入项目:cd test,运行项目:npm run dev
打包项目:cnpm run build
or
新建项目:vue create test_demo (可视化创建项目:vue ui)
进入项目:cd test_demo,运行项目:npm run serve
-
注:dev 是 vue2 的默认执行命令,serve 是vue3 的默认执行命令
报错:禁止运行脚本错误解决:set-ExecutionPolicy RemoteSigned
报错:'vue-cli-service' 不是内部或外部命令,也不是可运行的程序。需安装依赖:npm install
项目文件结构:
vue.cli 项目中 src 目录每个文件夹和文件的用法?
assets 放静态资源;
components 放组件;
router 定义路由相关的配置;
app.vue 是一个应用主组件;
main.js 是入口文件。
简单案例:
声明式渲染,将数据渲染进 DOM ,且响应式
const Counter = { data() { return { counter: 0 } } } Vue.createApp(Counter).mount(document) //创建并挂载 Vue 应用
指令:
指令带有前缀 v-,以表示它们是 Vue 提供的特殊属性。指令的值是单个 JavaScript 表达式,v-for 和 v-on 例外。
v-once,一次性插值,当数据改变时,插值处的内容不会更新。
v-text,响应式插值,等效 Mustache 插值,但 {{ }} 更灵活。
v-html,输出 HTML。容易导致 XSS 攻击,不要用在用户提交的内容上。
v-bind,响应地更新 HTML 属性
v-bind:title="message",单向数据绑定
v-bind:href="url" ……
缩写:v-bind:href -> :href
:class="{ 'active': isActive }" isActive为true时 同 class="active"
v-model,表单控件值的双向数据绑定。
其实它就是一个语法糖,这个背后就做了两个操作:
v-bind 绑定一个 value 属性;
v-on 指令给当前元素绑定 input 事件。
v-show,频繁切换的时候使用。
v-if,不要在一个元素上同时使用 v-if 和 v-for
v-else、v-else-if,必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
v-for,
v-for="todo in todos"
v-for="(todo, index) in todos",得到索引
v-for="(value, key, index) in object",循环对象,得到值、键、索引
v-for="n in 10",循环整数
v-show 和 v-if 指令的共同点和不同点?
共同点:都能控制元素的显示和隐藏;
不同点:v-show 本质就是通过控制 css 中的 display 设置为 none,控制隐藏,只会编译一次;
v-if 是动态的向 DOM树内添加或者删除 DOM元素,若初始值为 false,就不会编译了。而且 v-if 不停的销毁和创建比较消耗性能。
总结:如果要频繁切换某节点,使用 v-show(切换开销比较小,初始开销较大)。如果不需要频繁切换某节点使用 v-if(初始渲染开销较小,切换开销比较大)。
v-on,监听 DOM 事件
v-on:click="say('hi')"
缩写:v-on:click -> @click
多事件处理器:@click="one($event), two($event)"
事件修饰符,.stop .prevent .capture .self .once .passive。使用修饰符时,顺序很重要。
@click.once,点击事件将只会触发一次
按键修饰符,.enter .tab .delete .esc .space .up .down .left .right
@keyup.enter="submit",只有在 `key` 是 `Enter` 时调用 `vm.submit()`
系统修饰键, .ctrl .alt .shift .meta(Windows键)
@keyup.alt.enter,Alt + Enter 触发
@click.ctrl,Ctrl + Click 触发
.exact 修饰符
@click.ctrl,即使 Alt 或 Shift 被一同按下时也会触发
@click.ctrl.exact,有且只有 Ctrl 被按下的时候才触发
@click.exact,没有任何系统修饰符被按下的时候才触发
鼠标按钮修饰符,.left .right .middle。这些修饰符会限制处理函数仅响应特定的鼠标按钮。
v-on 监听多个方法?
<input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur, }">
动态参数:在指令参数中使用 JavaScript 表达式。
<a v-on:[eventName]="doSomething"> ... </a>,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus
修饰符:用于指出一个指令应该以特殊方式绑定。
<form v-on:submit.prevent="onSubmit">...</form>,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
$event,获取原始的 DOM 事件
ref="domName" 用法:this.$refs.domName
components,组件化,声明一组可用于组件实例中的组件。
//全局注册的组件可以在随后创建的 app 实例模板中使用 <div id="app"> <runoob></runoob> </div> <script> // 创建一个Vue 应用 const app = Vue.createApp({}) // 定义一个名为 runoob 的新全局组件 app.component('runoob', { template: '<h1>自定义组件!</h1>' }) app.mount('#app') </script>
//全局组件会造成用户下载的 JavaScript 做无谓的增加 //局部组件只能在这个实例中使用 <div id="app"> <runoob-a></runoob-a> </div> <script> var runoobA = { template: '<h1>自定义组件!</h1>' } const app = Vue.createApp({ components: { 'runoob-a': runoobA } }) app.mount('#app') </script>
prop,是子组件用来接受父组件传递过来的数据的一个自定义属性。
computed,计算属性,处理一些复杂逻辑。
<div id="app"> <p>原始字符串: {{ message }}</p> <p>计算后反转字符串: {{ reversedMessage }}</p> </div> <script> const app = { data() { return { message: 'RUNOOB!!' } }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } } Vue.createApp(app).mount('#app') </script> 得到: 原始字符串: RUNOOB!! 计算后反转字符串: !!BOONUR
computed vs methods:
两者效果相同,但 computed 依赖缓存,所以性能更好;
而使用 methods,在重新渲染的时候,函数总会重新调用执行。
watch,监听属性,来响应数据的变化。
<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button> </div> <script> const app = { data() { return { counter: 1 } } } vm = Vue.createApp(app).mount('#app') vm.$watch('counter', function(nval, oval) { alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!'); }); </script>
生命周期钩子:
created 函数是在数据注入后被调用,那么我们在这里就可以后台请求数据了,完成数据的导入,但是在这里我们不能够请求较大的数据,不然就会一直卡在这个函数里面。
mounted 函数是在实例被挂载之后调用,在此之后挂载完毕后就进行等待,数据更新之后就会调用 update 函数。如果我们进行操作要更新数据就可以放在这个函数里面。
update 函数是在视图数据更新之后调用,里面任意值改变后都会调用该函数。
destoryed 函数意思是实例销毁之后调用,比如说我的div标签被销毁了就会调用该函数。
其他:
特殊 attribute:key、ref、is…
避免使用大写字符来命名键名
property:特性。computed:计算。components:组件。
参考:vue常见面试题