Vue基础
渐进式Javascript框架
- 通过对框架的了解与运用程度,来决定其在整个项目的应用范围,最终可以独立的以框架方式完成整个web前端项目.
1.什么是Vue
- 可以独立的完成前后端分离式web项目的JavaScript框架
2.为什么学习Vue
- 三大主流框架: Angular React Vue
- 先进的前端设计模式: MVVM
- 可以完全脱离服务端,以前端代码复用的方式渲染整个页面: 组件化开发
3.特点
- 单页面web应用
- 数据驱动
- 数据的双向绑定
- 虚拟DOM
4.如何使用Vue
- 去百度官网并且下载
<div id='app'> {{ }} </div> <script src='js/vue.min.js'> new Vue({ el: '#app' }) </script> # 1.el为挂载点, 采用css3选择器语法与页面进行绑定,决定该vue对象控制的页面范围 # 2.挂载点只会匹配第一个匹配到的结果,所以一般采用id选择器 # 3.但是html与body标签不可以作为挂载点
5.vue变量
<body> <div id="app"> <p>{{ msg }}</p> <p>{{ info }}</p> </div> <div id="main"> <p>{{ msg }}</p> <p>{{ info }}</p> </div> </body> <script src="vue.min.js"></script> // data里面是为vue页面模板通过数据变量的. <script> let app = new Vue({ el: '#app', data: { msg: 'message', info: '变量信息' } }); let main = new Vue({ el: '#main', data: { msg: '傻逼', info: '脑残' } }); // 这种方式也可以调用 console.log(app.info); console.log(main.info); // 创建vue实例(new Vue) 传进去的字典(对象)的key值, 称之为实例成员(变量) // 访问实例成员,用vue实例.$成员名, eg: app.$el console.log(app.$el); console.log(app.$data); console.log(app.$data.info); </script>
6.Vue事件
<div id="app"> <p class="p1" v-on:click="fn">这是一个段落,被点击了{{ count }}下</p> <p class="p2" v-on:mouseover="overAction" v-on:mouseout="outAction" >该便签被{{ action }}</p> <div v-on:mouseover="overAction" v-on:mouseout="outAction">div被{{ action }}</div> </div> </body> <script src="js/vue.js"></script> <script> let app = new Vue({ el: '#app', data: { count: 0, action: '渲染', // fn: function () { // // console.log(app.count); // // app.count ++ // console.log(this); // this不是该vue实例对象,是顶级Window对象 // } }, // methods就是为vue实例提供事件函数的 methods: { fn: function () { // console.log(app.count); // app.count ++; // console.log(this); // this代表当前该vue实例对象 this.count ++ }, overAction: function () { this.action = '悬浮' }, outAction: function () { this.action = '离开' } } });
7.js的对象
// 1.js中没有字典,只要对象类型,可以把对象当做字典来使用 // 2.key本质是属性名,所以都是字符串类型(可以出现1,true),其实都是省略引号的字符串 let sex = '男'; let dic = { 'name': 'Owen', 1: 100, true: 12345, age: 18, // sex: 'sex', sex, }; console.log(dic['name']); console.log(dic['1']); console.log(dic['true']); console.log(dic['age']); console.log(dic.sex); dic.price = 3.5; console.log(dic.price); // 声明类创建对象,类可以实例化n个对象,哪个对象调用,this就代表谁 function People(name, age) { this.name = name; this.age = age; this.eat = function () { console.log(this.name + '在吃饭'); return 123 } } let p1 = new People('Owen', 17.5); console.log(p1.name); let res = p1.eat(); console.log(res); // 直接声明对象,{}内的key都属于当前对象的 // {}中的方法通常会简写 let stu1 = { name: '张三', age: 18, // eat: function () { // console.log(this.name + '在吃饭'); // } eat () { console.log(this.name + '在吃饭'); } }; stu1.eat() // 总结: // 1.{}中直接写一个变量:key与value是同名,value有该名变量提供值 // 2.es5下,所有的函数都可以作为类,类可以new声明对象,在函数中用 this.资源 为声明的对象提供资源 // 3.{}中出现的函数叫方法,方法可以简写 { fn: function(){} } => { fn(){} } </script>
8.文本指令
<div id="app"> <!-- 1、插值表达式,能完成变量渲染,变量基础运算,变量方法调用,不能完成复杂运算(一步解决不了的,不能出现;) --> <p>{{ msg }}</p> <p>{{ msg + '拼接内容' }}</p> <p>{{ msg[1] }}</p> <p>{{ msg.slice(2, 4) }}</p> <hr> <!--2、v-text:将所有内容做文本渲染 --> <p v-text="msg + '拼接内容'"></p> <!--3、v-html:可以解析html语法标签的文本 --> <p v-text="'<b>' + msg + '</b>'"></p> <p v-html="'<b>' + msg + '</b>'"></p> <p v-text="`<b>${msg}</b>`"></p> <p v-html="`<b>${msg}</b>`"></p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: '文本信息' } }) </script>
9.vue过滤器
<div id="app"> <!-- 默认将msg作为参数传给filterFn --> <p>{{ msg | filterFn }}</p> <!--过滤器串联--> <p>{{ num | f1 | f2 }}</p> <!--可以同时对多个变量进行过滤,变量用,分割,过滤器还可以额外传入参数辅助过滤--> <!--过滤器方法接收所有传入的参数,按传入的位置进行接收--> <p>{{ msg, num | f3(666, '好的') }}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: '文本内容', num: 1 }, filters: { filterFn(v1, v2) { // console.log(v1); // console.log(v2); return v1; }, f1(v1) { return v1 * 100; }, f2(v1) { return v1 * 100; }, f3(v1, v2, v3, v4) { console.log(v1); console.log(v2); console.log(v3); console.log(v4); } } })
10.事件的指令
<div id="app"> <!--事件指令:v-on:事件名="事件函数" --> <!--简写:@事件名="事件函数" --> <p v-on:click="f1">被点击了{{ count }}下</p> <hr> <p @click="f2">{{ p2 }}</p> <hr> <!--绑定的事件函数可以添加(),添加括号就代表要传递参数--> <ul> <li @click="f3(100)">{{ arr[0] }}</li> <li @click="f3(200)">{{ arr[1] }}</li> <li @click="f3(300)">{{ arr[2] }}</li> </ul> <ul> <li @click="f4(1)">{{ arr[0] }}</li> <li @click="f4(2)">{{ arr[1] }}</li> <li @click="f4(0)">{{ arr[2] }}</li> </ul> <hr> <!--绑定的事件函数如果没有传递参数,默认传入 事件对象 --> <div class="box" @click="f5"></div> <hr> <!--事件函数一旦添加传参(),系统就不再传递任何参数,需要事件对象时,可以手动传入 $event --> <div class="box" @click="f6(10, $event)"></div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { count: 0, p2: '第二个p', arr: [1, 2, 3], }, methods: { f1() { this.count ++ }, f2() { console.log(this.p2) }, f3(num) { console.log(num); }, f4(index) { console.log(this.arr[index]); }, f5(ev, b) { console.log(ev); console.log(b); }, f6(num, ev) { console.log(num); console.log(ev); } }, })
11.属性指令
<head> <meta charset="UTF-8"> <title>属性指令</title> <style> .b1 { width: 100px; height: 100px; background-color: red; } .box1 { width: 150px; height: 150px; background-color: darkturquoise; transition: .3s; } .box2 { width: 300px; height: 100px; background-color: darkgoldenrod; transition: .3s; } .circle { border-radius: 50%; } </style> </head> <body> <div id="app"> <!--1.下方的class、id、title、abc等是div标签的属性,属性指令就是控制它们的--> <div class="b1" id="b1" v-bind:title="title" :abc="xyz"></div> <!--2.属性指令:v-bind:属性名="变量",简写方式 :属性名="变量" --> <!--3.属性指令操作 style 属性--> <div style="width: 200px;height: 200px;background-color: greenyellow"></div> <!-- 通常:变量值为字典 --> <div :style="mys1"></div> <!-- 了解:{中可以用多个变量控制多个属性细节} --> <div :style="{width: w,height: '200px',backgroundColor: 'deeppink'}"></div> <!--重点:一般vue都是结合原生css来完成样式控制 --> <!--<div :class="c1"></div>--> <!--class可以写两份,一份写死,一份有vue控制--> <div class="box1" :class="c1"></div> <!--{}控制类名,key为类名,key对应的值为bool类型,决定该类名是否起作用--> <div :class="{box2:true, circle:cable}" @mouseover="changeCable(1)" @mouseout="changeCable(0)"></div> <!--[]控制多个类名--> <div :class="[c3, c4]"></div> </div> </body> <script src="js/vue.js"></script> <script> let app = new Vue({ el: '#app', data: { title: '12345', xyz: 'opq', mys1: { width: '200px', height: '200px', // 'background-color': 'greenyellow' backgroundColor: 'pink', }, w: '200px', c1: 'box1', c2: 'circle', cable: false, c3: 'box1', c4: 'circle' }, methods: { changeCable(n) { this.cable = n; } } }); // 实现一个动图 setInterval(function () { // app.c1 = app.c1 === 'box1' ? 'box2' : 'box1'; if (app.c1 === 'box1') { app.c1 = 'box2'; } else { app.c1 = 'box1'; } }, 300)
12.表单属性
<div id="app"> <form action=""> <!-- 属性指令: v-model='变量',控制的是表单元素的value值--> <!-- 普通表单元素,用v-model直接绑定变量控制value值--> <input type="text" v-model="v1"> <input type="text" v-model="v1"> <p>{{ v1 }}</p> <hr> <!-- 单一复选框--> 同意: <input type="checkbox" name="agree" value="v2"> <br> <!-- 多个复选框--> <input type="checkbox" name="hobbies" value="male" v-model="v3"> <input type="checkbox" name="hobbies" value="female" v-model="v3"> <input type="checkbox" name="hobbies" value="wow" v-model="v3"> <p>{{ v3 }}</p> <!-- 单选框--> 中午吃啥: 肉:<input type="radio" name="food" value="rou" v-model="v4"> 菜:<input type="radio" name="food" value="cai" v-model="v4"> <p>{{ v4 }}</p> </form> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { v1:'', v2: false, v3: ['male'], v4: 'rou', } })
13.条件指令
<div id="app"> <!-- 条件指令: v-if="true|false",为假时,在页面上不渲染,可以隐藏标签中的信息 v-show="true|false", 为假时, 在页面中用display:none渲染,虽然没有展示,但是在页面结构中 --> <p v-if="v1 === '2'">if指令</p> <p v-show="v1 === '1'">show指令</p> <!-- v-if是一个家族 v-if v-else-if v-else 1.上分支成立, 下分支会被屏蔽 2.else分支只要在所有上分支都为假时显示. --> <p v-if="v1 === '1'">if分支</p> <p v-else-if="v1 === '2'">elif分支1</p> <p v-else-if="v1 === '3'">elif分支2</p> <p v-else>else分支</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { v1: '2' } })
14.循环指令
<div id="app"> <!-- 循环指令: v-for="" 语法: v-for="成员 in 容器" --> <!-- 字符串,数组,对象都可以遍历值--> <div> <p v-for="(v, k, i) in arr">{{ i }}-{{ k }}:{{ v }}</p> </div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { arr: [ { name: 'Kang', age: 18, }, { name: 'Wei', age: 17 }, ] } })
15.计算属性成员
div id='app'> <input type="text" v-model="v1"> + <input type="text" v-model="v2"> = <button>{{ res }}</button> </div> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { v1: '', v2: '', }, // 1.computed中定义的是方法属性,data中定义的也是属性,所以不需要重复定义 // 2.方法属性的值来源于绑定的方法的返回值 // 3.方法属性必须在页面中渲染后,绑定的方法才会被启用. // 4.方法中出现的所有变量都会被监听,任何变量发生值更新都会调用一次绑定的方法. // 5.方法属性值不能手动设置,必须通过绑定的方法进行设置 computed: { res () { return this.v1 && this.v2 ? +this.v1 + +this.v2 : '结果'; } } }) </script>
16.属性的监听
<div id="app"> <p> 姓名:<input type="text" v-model="full_name"> </p> <p> 姓:<span>{{ first_name }}</span> </p> <p> 名:<span>{{ last_name }}</span> </p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { full_name: '', first_name: '', last_name: '', }, watch: { // 1.watch中给已有的属性色值监听方法. // 2.监听的属性一旦发生更新,就会调用监听方法,在方法中完成响应的逻辑 // 3.监听方法不需要返回值(返回值只有主动结束方法的作用) full_name() { if (this.full_name.length === 2) { k_v_arr = this.full_name.split(''); this.first_name = k_v_arr[0]; this.last_name = k_v_arr[1]; } } } })
Vue组件
<div id="app"> {{ msg }} </div> </body> <script src="js/vue.js"></script> <script> // 1.组件: 由html,css,js三部分组成的独立单位,可以类似于变量,重复使用 // 2.组件其实就是vue实例(对象),一个组件就是一个vue实例(对象) // 3.new Vue()产生的也是实例(对象),所以也是组件,我们称之为根组件,一个页面 // 建议只出现一个根组件, // 4.组件的html页面结构由template 实例成员提供. // template提供的html结构是用来构造虚拟DOM // 真实的DOM最终会被虚拟DOM替换 // 根组件一般不提供template,就由挂载点el来提供构建虚拟DOM的页面结构, // 根组件如果提供了template,还需要设置挂载点作为替换占位 // template模板有且只有一个根标签 let c1 = ''; new Vue({ el: '#app', data: { msg: '123', c1: 'red' }, template:` <div id="app"> <p :style="{color:c1}">{{ msg }}</p> <p :style="clickAction">{{ msg }}</p> `, methods: { clickAction() { console.log(this.msg) } } })
1.子组件
<div id="app"> <my-tag></my-tag> <tag></tag> </div> </body> <script src="js/vue.js"></script> <!--1.定义组件 2.注册组件 3.使用组件--> <!--如何定义子组件: 组件就是一个普通的对象,内部采用vue语法结构,被vue注册解释后,就会成为vue组件--> <script> let myTag = { template:` <div> <h3>子组件</h3> <p>我是自定义子组件</p> </div> `, }; // 了解: 全局组件, 不需要注册就可以直接使用 Vue.component('tag', { template:` <div> <h3>全局组件</h3> <p>我是自定义的全局组件</p> `, }); // 子组件注册 new Vue({ el: '#app', components: { myTag, } }) </script> </html>
父传子
<div id="app"> <div class="wrap"> <!-- 通过绑定自定义属性,传送给子--> 第一步 <tag v-for="dog in dogs" :dog="dog"></tag> </div> </div> </body> <script src="js/vue.js"></script> <script> let dogs = [ { title: '一号', img: 'img/1.jpg'}, { title: '二号', img: 'img/2.jpg'}, { title: '三号', img: 'img/3.jpg'}, { title: '四号', img: 'img/4.jpg'} ]; // 子组件通过props反射机制,来拿到父传过来的值. let tag = { props: ['dog'], 第二步 template: ` <div class="box"> <img :src="dog.img" alt=""> <p> <b> {{ dog.title }} </b> </p> <p @click="fn"> 点击:<b>{{ num }}</b> </p> `, data () { return { num:0, } }, methods: { fn(){ this.num ++ } }, }; new Vue({ el: '#app', data: { dogs, }, components: { tag, } }); </script>
子传父
<div id="app"> <h1>{{ title }}</h1> <tag @self_action="changeTitle"></tag> # 第三步拿取 </div> </body> <script src="js/vue.js"></script> <script> let tag = { template:` <div> <input type="text" v-model="sub_title"> </div> `, data() { return { sub_title:'' # 第一步 } }, // 将sub_title与父级的title建立链接 // 使用$emit激活(触发)self_action自定义事件 watch: { sub_title() { this.$emit('self_action', this.sub_title) # 第二步送过去 } } }; new Vue({ el: '#app', components: { tag, }, data: { title: '父级初始标题' }, // 拿到子传过来的 # 第四步使用. methods: { changeTitle(sub_title) { this.title = sub_title ? sub_title: '父级初始标题'; } } })