Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
通过vue 文档官网下载vue 开发版本将下载的 js 文件放到项目 js 目录中。
通过<script>标签直接导入:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.js"></script>
或压缩版:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.min.js"></script>
获取谷歌浏览器插件
获取火狐浏览器插件
获取Edge 浏览器插件
直接安装插件即可
二、Hello World 案例
html1
| <div id="demo1">{{str}}</div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo1', data:{ str:'Hello World' } })
|
三、案例分析
当两个容器含有同一类名时:
html1 2 3 4 5 6
| <div class="demo2"> <div>{{str}}</div> </div> <div class="demo2"> <div>{{str}}</div> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'.demo2', data:{ str:'Hello World' } })
|
容器与 Vue 实例为一对一关系,且 Vue 实例有且只有一个。
中的语句写 js 表达式,且语句可以读取到 data 中的属性。
data 中的属性发生变化,容器中语句引用的地方也会更新。
四、模板语法
(一)、插值语法
html1 2 3
| <div id="demo3"> <div>你好,{{name}}</div> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo3', data:{ name:'Tom', } })
|
(二)、指令语法
html1 2 3
| <div id="demo4"> <a v-bind:href="url">跳转到百度</a> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo4', data:{ url:'https://baidu.com/' } })
|
五、数据绑定
(一)、单向数据绑定
html1 2 3
| <div id="demo5"> <input type="text" :value="str"> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo5', data:{ str:'数据单向绑定' } })
|
(二)、双向数据绑定
html1 2 3
| <div id="demo6"> <input type="text" v-model:value="str"> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo6', data:{ str:'数据双向绑定' } })
|
v-model 只能用于表单类元素如<h2 v-model:x="name"></h2>
是错误的形式
修改 v-model 绑定的值时,data 里的值也会一同改变。
v-model:value 可简写为 v-model,因为 v-model 默认值为 value
![v-model]()
六、el 与 data 的两种写法
(一)、el 绑定的第二种方法
html1 2 3
| <div id="demo7"> <div>你好,{{name}}</div> </div>
|
javascript1 2 3 4 5 6
| const vue = new Vue({ data:{ name:'Tom', } }) vue.$mount('#demo7');
|
(二)、data的第二种写法
html1 2 3
| <div id="demo8"> <div>你好,{{name}}</div> </div>
|
javascript1 2 3 4 5 6 7 8
| var vm = new Vue({ el:'#demo8', data:function(){ return { name:'Tom' } } })
|
七、Object.defineProperty()
Object.defineProperty()用于为对象添加属性。
1 2 3 4
| let person = { name: "Tom", sex: "male", };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Object.defineProperty(person, "age", { value: 18, enumerable: true, writable: true, configurable: true, get: function () { return value + 1; }, get() { return value + 1; }, set(value) { return value + 1; }, });
|
八、事件
(一)、事件处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <button v-on:click="show1">非简写点击事件</button> <button @click="show2">简写点击事件</button> <script> new Vue({ el: "element", data: {}, method: { show1(e) { }, show2(e) {}, }, }); </script>
|
(二)、事件修饰符
1
| <a href="https://baidu.com" @click.prevent="showInfo">提示信息</a>
|
修饰符:
(三)、键盘事件
1 2
| <input type="text" @keydown.enter="show" /> <input type="text" @keyup.enter="show" />
|
别名 | 名称 |
---|
enter | 回车 |
delete | 删除 |
esc | 退出 |
space | 空格 |
tab | 换行 |
up | 上 |
down | 下 |
left | 左 |
right | 右 |
未提供别名的按键可用原始 key 值绑定,但要转换为短横线命名如:CapsLock
->caps-lock
。
系统修饰键:ctrl,alt,shift,win
- 配合 keyup 使用:按下修饰键同时按下其他键,再放开其他键。
- 配合 keydown 使用
通过键码(不推荐)如:keydown.13 为回车。
通过Vue.config.keyCodes.自定义名 = 键码
这样自定义的名称就和键码联系起来了。
九、计算属性
1 2 3 4 5 6 7 8 9 10
| new Vue({ el: ".el", data: {}, computed: { comfn: { get() {}, set(value) {}, }, }, });
|
计算属性:
当计算属性只需要get
时,可写为:
1 2 3 4 5 6 7
| new Vue({ el: ".el", data: {}, computed: { comfn() {}, }, });
|
html1 2 3 4 5 6
| <div id="demo9"> <input type="text" v-model:value="x"> <input type="text" v-model:value="m"> <div>{{full}}<div> </div> </div></div>
|
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var vm = new Vue({ el:'#demo9', data:{ x:"张", m:"三" }, computed:{ full:{ get(){ return this.x+"-"+this.m; } } } })
|
十、监视属性
1 2 3 4 5 6 7 8 9 10 11 12 13
| new Vue({ el: ".el", data: { wafn: "", }, watch: { wafn: { immediate: false, handler(newValue, oldValue) {}, }, }, });
|
或通过 vm 对象进行添加
1 2 3 4 5 6 7 8 9 10
| var vm = new Vue({ el: ".el", data: { wafn: "", }, }); vm.$watch("wafn", { immediate: false, handler(newValue, oldValue) {}, });
|
深度监视
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| new Vue({ el: ".el", data: { nums: { a: 1, b: 1, }, }, watch: { nums: { handler(newValue, oldValue) {}, }, }, });
|
如果使用以上形式会检测不到 num 内 a,b 值的变化,需要为监视函数 nums 添加 deep:true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| new Vue({ el: ".el", data: { nums: { a: 1, b: 1, }, }, watch: { nums: { deep: true, handler(newValue, oldValue) {}, }, }, });
|
十一、绑定 class 样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="root"> <div :class="cl"></div> <div :class="cl1"></div> <div :style="{fontSize: fsize+'px'}"></div> </div> <script> new Vue({ el: "#root", data: { cl: "className", cl1: ["className1", "className2", "className3"], fsize: 10, }, }); </script>
|
对象形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <div id="root"> <div :class="clObj"></div> <div :style="stObj"></div> </div> <script> new Vue({ el: "#root", data: { clObj: { className1: true, className2: false, }, stObj: { fontSize: "40px", }, }, }); </script>
|
十二、条件渲染
(一)、v-show
1 2
| <div v-show:"true"></div> <div v-show:"false"></div>
|
(二)、v-if
1 2 3
| <div v-if:"true"></div> <div v-else-if:"false"></div> <div v-if:"false"></div>
|
区别:v-show 为 false 时会将模板解析,但会添加 dispaly:none 属性,所以不显示。
v-if 为 false 时则直接不解析。
十三、列表渲染
- {{p.id}}-{{p.name}}-{{p.age}}
html1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="demo10"> <ul> <li v-for="p in persons" :key="p.id">{{p.id}}-{{p.name}}-{{p.age}}</li> </ul> <ul> <li v-for="(o,index) in obj" :key="index">{{index}}-{{o}}</li> </ul> <ul> <li v-for="(t,index) in str" :key="index">{{index}}-{{t}}</li> </ul> <ul> <li v-for="(n) in 3" :key="index">{{n}}</li> </ul> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| new Vue({ el:'#demo10', data:{ persons:[ {id:'1',name:'person1',age:'20'}, {id:'1',name:'person2',age:'21'}, {id:'1',name:'person3',age:'22'} ], obj:{ data1:"test", bool: true, }, str:"hello" }, })
|
每个key都应唯一
v-for可以从列表,对象,字符串中去除对象或属性。
十四、列表过滤
html1 2 3 4 5 6
| <div id="demo11"> <input type="text" v-model:value="keyWord"> <ul> <li v-for="(p,index) of filpersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}</li> </ul> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| new Vue({ el:'#demo11', data:{ persons:[ {id:'001',name:'马冬梅',age:30,sex:'女'}, {id:'002',name:'周冬雨',age:31,sex:'女'}, {id:'003',name:'周杰伦',age:18,sex:'男'}, {id:'004',name:'温兆伦',age:19,sex:'男'} ], keyWord='', filpersons:[ ] }, watch:{ keyWord:{ immediate:true, handler(val) { this.filpersons = this.persons.filter((p)=>{ return p.name.indexOf(val)!==-1; }) } } } });
|
十五、Vue 监视数据
![image-20220713190744008]()
图片来源:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=37
十六、过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div id="root"> <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.3/dayjs.min.js"</script> <h3>时间是:{{time | timeFormater}}</h3> </div> <script> new Vue({ el:"#root", dara:{ time:1657717090991 }, filters:{ timeFormater(val){ return dayjs(val).format('YYYY年MM月DD日 HH:mm:ss') } } }) </script>
|
在管道符后写过滤函数例:
格式化前时间是:{{time}}
格式化后时间是:{{time | timeFormater}}
html1 2 3 4 5
| <div id="demo12"> <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.3/dayjs.min.js"></script> <h3>格式化前时间是:{{time}}</h3> <h3>格式化后时间是:{{time | timeFormater}}</h3> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11
| new Vue({ el:'#demo12', data:{ time:1657720756624 }, filters:{ timeFormater(val){ return dayjs(val).format('YYYY年MM月DD日 HH:mm:ss') } } });
|
全局过滤器:
1 2 3 4
| Vue.filter("过滤器名", function () { 函数体; return 结果; });
|
十七、内置指令
(一)、v-text
html1 2 3
| <div id="demo13"> <div v-text="txt"></div> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo13', data:{ txt:'这是文本内容' } });
|
(二)、v-html
v-html 支持结构解析而 v-text 不支持
html1 2 3
| <div id="demo14"> <div v-html="html"></div> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo14', data:{ html:'<h3>v-html插入的内容</h3>' } });
|
注意
在网站上动态渲染 html 是非常危险的,不要将 v-html 使用在用户提交内容上
(三)、v-cloak
解决由于网速等问题,导致 vuejs 不能及时加载,使未经渲染过的模板直接出现在网站上,页面闪动。
1 2 3 4 5 6 7
| <style> [v-cloak] { //属性选择器 display: none; } </style> <h3 v-cloak>v-cloak的元素</h3>
|
当 vuejs 加载完成后,会自动将页面中的 v-cloak 属性删除,这样被隐藏的界面就可以显示出来了。
(四)、v-once
1 2 3 4 5 6 7 8 9 10 11
| <div id="demo16"> <div v-once>{{n}}</div> </div> <script> new Vue({ el: "#demo16", data: { n: 1, }, }); </script>
|
当标签含有属性 v-once 后,则模板渲染一次后就成为静态资源不再重新渲染,即使源数据发生了改变。
(五)、v-pre
当标签添加 v-pre 后,该标签的模板就不会再被解析,一般用于优化代码。
html1 2 3
| <div id="demo15"> <div v-pre>{{str}}</div> </div>
|
javascript1 2 3 4 5 6
| new Vue({ el:'#demo15', data:{ str:'测试内容' } });
|
十八、自定义指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div id="root"> <h2 v-x="n"></h2> </div> <script> new Vue({ el: "#root", data: { n: 99, }, directives: { x(element, binding) { element.innerHTML = binding.value * 2; }, }, }); </script>
|
html1 2 3 4 5
| <div id="demo17"> <div>{{n}}</div> <div v-x="n"></div> <button @click="n++">点击加一</button> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11
| new Vue({ el:'#demo17', data:{ n:0 }, directives:{ x(element,binding){ element.innerHTML=binding.value*2 } } });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <div id="root"> <h2 v-x="n"></h2> </div> <script> new Vue({ el: "#root", data: { n: 99, }, directives: { x: { bind(element, binding) { element.innerHTML = binding.value * 2; }, inserted(element, binding) { element.focus(); }, update(element, binding) { element.innerHTML = binding.value * 2; }, }, }, }); </script>
|
全局指令:
1 2 3 4 5
| Vue.directive("指令名", { bind(element, binding) {}, inserted(element, binding) {}, update(element, binding) {}, });
|
十九、生命周期(重要)
生命周期指生命周期函数,是 Vue 在不同时刻调用的一些特殊函数,生命周期名不可被改变。
生命周期图示
![Vue 实例生命周期]()
流程:
1 2
| graph TB beforeCreate --> created --> beforeMount --> mounted --> beforeUpdate --> updated --> beforeDestroy --> destroyed
|
生命周期详细内容:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=50
二十、组件
(一)、非单文件组件
html1 2 3 4
| <div id="demo18"> <school></school> <student></student> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const school = Vue.extend({ template:` <div> <div>{{name}}</div> <div>{{add}}</div> </div> `, data(){ return { name:"testSchoolName", add:"testSchoolAdd" } } }) const student = Vue.extend({ template:` <div> <div>{{name}}</div> <div>{{age}}</div> </div> `, data(){ return { name:"testStuName", age:"testStuAge" } } }) new Vue({ el:'#demo18', components:{ school, student } })
|
(二)、组件的嵌套
html1 2 3
| <div id="demo19"> <app></app> </div>
|
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| const school = Vue.extend({ template:` <div> <div>{{name}}</div> <div>{{add}}</div> </div> `, data(){ return { name:"testSchoolName", add:"testSchoolAdd" } } }) const student = Vue.extend({ template:` <div> <div>{{name}}</div> <div>{{age}}</div> </div> `, data(){ return { name:"testStuName", age:"testStuAge" } } }) const app = Vue.extend({ template:` <div> <school></school> <student></student> </div> `, components:{ school, student } }) new Vue({ el:'#demo19', components:{ app } })
|
二十一、重要内置关系
https://www.bilibili.com/video/BV1Zy4y1K7SH?p=59
![vue与vueComponent的关系]()