JS前端三大框架
1、Angular
2、Vue(最流行:45%-50%)
3、React(流行:40%)
Vue框架
Vue 是一套用于构建用户界面的渐进式框架。被设计为可以自底向上逐层应用。 Vue 的核心库只关注视图层,另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue的使用
简单的可以直接当成JQuery来的使用就是了。
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
引入到需要用的Vue框架的HTML中就可以了。
1.创建Vue实例
<!--html代码-->
<div id="app">
{{message}}
<p>
用户名:{{username}}
</p>
</div>
<!--js代码-->
let app = new Vue({
el: "#app", //以选择器名指向容器标签,即挂载点
data:{
//数据
}
})
2.Vue的生命周期
生命周期勾子:是在Vue在生命周期各个阶段,我们可以定义它要做什么的函数。
(1)beforeCreate():创建前状态
(2)created():创建完毕状态
(3) beforeMount():挂载前状态
(4)mounted():挂载结束状态
(5)beforeUpdate():更新前状态
(6)updated():更新完成状态
(7)beforeDestroy() :销毁前状态
(8)destroyed() :销毁完成状态
模板语法
所有模板语法就是VUE的DOM容器可以直接写的类JS语法,一般用于变量的直接显示或者一些简单的表达式直接执行
- 模板语法不能在标签内部生效
<sapn>{{ 变量名 }}</span>
使用时注意Vue的模板语法已经做了防注入的功能,所以并不能直接输出HTML代码
3.Vue指令
(1)v-html
用于输出html。
<div id="app">
<p v-html="html"></p>
</div>
var app = new Vue({
el: "#app",
data: {
html: "<b>v-html</b>"
}
});
(2)v-text
用于操作纯文本,它会替代显示对应的数据对象上的值。
v-text可以简写为{{}},并且支持逻辑运算。
<div id="app">
{{ message }}
</div>
var app = new Vue({
el : '#app',
data : {
message : 'hello world'
}
})
注意:vue中有个指令叫做 v-once 可以通过v-once与v-text结合,实现仅执行一次性的插值
<span v-once>这个将不会随message属性的改变而改变: {{ message }}</span>
v-html和v-text的区别
v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。
(3)v-if 和 v-show
A. v-if
当属性值为true是,该标签显示;
为false时,则不出现,相当于该标签直接被销毁
<div id="app">
<p v-if="a">我显示出来了</p>
</div>
let app = new Vue({
el:"#app",
data:{
a:true/false,
}
})
B. v-show
当属性值为true时,该标签显示,否则则隐藏,相当于display:none。
<div id="app">
<p v-show="a">我显示出来了</p>
</div>
let app = new Vue({
el:"#app",
data:{
a:true/false,
}
})
C. v-if 和 v-show 的区别
v-if 属性值为false时,标签直接销毁,v-show 属性值为false时,标签存在,只是相当于添加了display:none 属性把标签隐藏了。
(3)v-for
A. 遍历数组
<!-- 1 基础用法 -->
<div v-for="item in items">
{{ item.text }}
</div>
<!-- item 为当前项,index 为索引 -->
<p v-for="(item, index) in list">{{item}} -- {{index}}</p>
<!-- item 为值,key 为键,index 为索引 -->
<p v-for="(item, key, index) in obj">{{item}} -- {{key}}</p>
<p v-for="item in 10">{{item}}</p>
<div class="app">
<ul>
<li v-for="o in arr">
姓名:{{ o.name }}, 性别:{{ o.age }}
</li>
</ul>
</div>
let vue = new Vue({
el:".app",
data:{
arr: [
{name:"alex",age:18},
{name:"sky",age:20},
{name:"rose",age:22},
],
}
})
B. 遍历对象(加入索引)
<div class="app">
<ul>
<li v-for="(value,name,index) in obj">
{{ index }}、{{ name }} : {{ value }}
</li>
</ul>
</div>
let vue = new Vue({
el:".app",
data:{
obj:{
name:"alex",
age:18,
sex:"boy",
}
}
})
C. 在使用v-for或者其它使用了页面模板的数据时数据的更新只通过某些指定的方法进行更新。不然页面数据无法更新,用以下方法:
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
D. key属性
-
推荐:使用 v-for 的时候提供 key 属性,以获得性能提升。
-
说明:使用 key,VUE会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
(4)v-bind(简写:)
- 当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM,这个属性是用于绑定标签本身拥有属性值的指令
- 语法:v-bind:title=“msg”
<a v-bind:href="url"></a> <!--<a :href="url"></a>-->
<script>
var vm = new Vue({
el: '#app',
data: {
url: 'http://www.baidu.com'
}
})
</script>
<div id="app">
<ul>
<li v-for="a in list">
<a :href="a.url" :title="a.title"> //模板语法在标签内不生效
<img :src="a.img" :alt="a.title">
</a>
</li>
</ul>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
list:[
{title:'耗子尾汁', url:"http://www.qq.com", img:"./1.jpg"},
{title:'连五鞭', url:"http://www.163.com", img:"./1.jpg"},
{title:'年轻人不讲武德', url:"http://www.jd.com", img:"./1.jpg"},
{title:'老同志了', url:"http://www.taobao.com", img:"./1.jpg"},
{title:'鬼畜新星', url:"http://www.vip.com", img:"./1.jpg"},
]
}
})
</script>
(5)v-on(简写@click)
- 事件绑定
- 语法:v-on:click=“say” 或者 v-on:click=“say (‘参数’, $event)”
- 说明:绑定的事件从 methods 中获取
<div class="app">
<a v-on:click="doSomething("123")"></a>
</div>
<script>
let app = new Vue({
el:".app",
data:{},
// methods属性用来给vue实例提供方法(事件)
methods:{
doSomething:function(str){
console.log(str)
},
}
})
</script>
<div id="app">
<p>
<button @click="++count">你点了我{{count}}次了!!</button>
</p>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
count: 0
},
})
</script>
事件修饰符
- .stop 阻止冒泡,调用 event.stopPropagation()
- .prevent 阻止默认事件,调用 event.preventDefault()
- .capture 添加事件侦听器时使用事件捕获模式
- .self 只当事件在该元素本身(比如不是子元素)触发时触发回调
- .once 事件只触发一次
- .passive
<!-- 阻止单击事件继续传播(即阻止事件冒泡) -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
按键修饰符
.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
新增:.ctrl、.alt、.shift、.meta(系统键(win键、mac键…))
<div id="app">
弹起回车触发:
<input type="text" @keyup.enter="down"><br/>
按下alt+ctrl触发:
<input type="text" @keydown.alt.ctrl="down"><br/>
弹起f2触发:
<input type="text" @keyup.113="down"><br/>
弹起f4触发:
<input type="text" @keyup.f4="down"><br/>
</div>
<script>
// 全局定义未被定义的键盘码
Vue.config.keyCodes.f4=115;
var vm=new Vue({
el:'#app',
methods:{
down:function () {
console.log(1);
}
}
})
</script>
(6)v-model
- 作用:在表单 input、textarea、select 元素上创建双向数据绑定
- 说明:监听用户的输入事件以更新数据
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<div id="app">
<p>
<input type="text" v-model="name" >
</p>
<p>
{{ name }}
</p>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
name:'',
},
})
</script>
div id="app">
<p>
<input type="text" v-model="name" >
是否显示值:<input type="radio" name="choose" checked @click="show = true" >是
<input type="radio" name="choose" @click="show = false" >否
</p>
<p v-if="show">
{{ name }}
</p>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
show:true,
name:'',
},
})
</script>
(7)class 与 style 绑定
绑定动态样式名(class)
通过直接绑定class名来进行动态调用class的目的。
a. 直接绑定类名
<div :class="classa">直接绑定类</div> /* classa为类名 */
b. 判断是否为true,为true显示样式,为false不显示
<div :class="flag?classa:classb"></div>
c. 实例:
<style>
.box{
width: 300px;
height: 300px;
margin: 100px auto;
border: 1px black solid;
}
.box1{
background-color: yellow;
}
.box2{
background-color: hotpink;
}
</style>
<div id="app">
<!--<div class="box" v-bind:class="{class名:boolean值}" @click="classa = !classa">-->
<div class="box" v-bind:class="{box1:classa,box2:!classa}" @click="classa = !classa"></div>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
classa:true,
},
})
</script>
d. 绑定很多个类,比如数组
<div :class="[classa,classc]">合并所有的类</div>
绑定内联样式(style)
直接绑定style来为标签样式进行修改,这种修改也是动态的。
<!--<div class="box" :style="{属性:属性值}" @click="changeBg"></div>-->
<div class="box" :style="{background:bg}" @click="changeBg"></div>
也可以绑定多个样式,比如数组
<div :style="[stylea,styleb]">合并所有的样式</div>
(9)v-bind 和 v-model 的区别
A. v-bind用来绑定数据和属性以及表达式。是单向绑定。
a. 绑的是html元素的属性或者组件的prop,而不是像model那样绑的是表单控件的值。
b. 在绑定 class 或 style attribute 时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。
c. 在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。
d. 没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。
B. v-model使用在表单中,实现数据的双向绑定,在表单元素外不起作用。局限于**input、textarea、select、组件(components)**标签。
4.计算属性(computed)和侦听器(watch)
(1)计算属性
- 计算属性是Vue中把方法当成属性值来使用的一个代表。
- 在Vue实例中使用的 computed 这个属性来完成
<div id="app">
<p>
商品单价:<input type="number" v-model="price" >元
</p>
<p>
商品数量:<input type="number" v-model="number" >件
</p>
<p>
共计:{{ total }}元
</p>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
price:0,
number:0,
// total:0,
},
computed:{
total(){
return this.price * this.number;
}
}
})
</script>
- 在计算属性中定义的方法在模板中就会直接当成变量(属性)来使用。使用的是该方法的返回值。所以使用计算属性一定需要用返回值 。
- 在计算属性中只要涉及到的变量发生变化就会自动调用计算属性来完成更新新的返回值
computed和methods的对比
两种方法用起来差不多,那我们为什么要用computed呢?
因为在代码运行时如果methods中的方法调用几次,方法就执行几次;而computed不同,它会被vue内部缓存起来,不管调用多少次,它都只执行一次,大大减少了服务器的压力。
(2)侦听器
侦听器的基本作用就是对属性进行侦听,一旦侦听的属性发生变化。侦器就会触发,从而可以执行指定的语句。
- 格式
// watch就是Vue中用于侦指定属性的选项
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
}
- 例子
<div id="app">
<p>
<input type="text" v-model="name" >
<button @click="changeName">修改值</button>
</p>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
name:"alex",
},
watch:{
name(newValue,oldValue){
console.log("旧值:" + oldValue)
console.log("新值:" + newValue)
if(newValue == "tom"){
alert("这个名字不能输入!")
this.name = ""
}
}
},
methods:{
changeName(){
this.name = "sky"
}
}
})
</script>
(3)计算属性和侦听器的区别
- 计算属性:改变一个或多个响应式元素的值,去修改一个响应式元素的值。
- 侦听器:改变一个响应式元素的值,去修改多个响应式元素的值。
5.Vue组件
组件开发就是活字印刷一样。把页面中的各个区块与其功能进行剥离,然后根据需要再进行组合。
(1)组件的注册
全局注册
在组件中设置数据的方法是跟Vue实例有点不同。data是一个函数并且它是直接返回一个对象,而不是像Vue实例中直接就是一个对象
<div class="app">
<!--调用注册的组件-->
<button-counter></button-counter>
</div>
<script>
//全局注册
//注册组件
Vue.component('button-counter',{
data:function(){
return{}
},
template: '<h1>你来自哪里?</h1>'
})
//实例化Vue
let app = new Vue({
el:".app",
data:{},
})
</script>
在注册组件时,注册组件语句一定要写在实例化Vue语句前,因为vue的实例化会把全局注册的组件注册到当前实例中,实例化完成你再全局注册组件是对这个实例不起作用的,所以第一段代码是已经实例化完毕vue了又去注册了组件,这样即使在调用组件也不会起作用了。
局部注册
由于使用了全局注册组件的话,那无论这个组件要使用还是不使用,Vue都会进行执行。这样就会导致资源的浪费。局部注册组件的好处就是,按需要进行组件加入从而减少资源的浪费。
<div class="app">
<button-counter></button-counter>
</div>
<script>
//注册组件
let Child = {
data:function(){
return{}
}
template: '<h1>你来自哪里?</h1>'
}
//创建根实例
new Vue({
el:".app",
//components属性是实例化Vue中的一个选项,这个选项就是进行组件的指定。
//属性名就是组件名,值就是组件的内容。
components:{
// <button-counter> 将只在父模板可用
"button-counter":Child,
}
})
</script>
例子
<div id="app">
<header-counter
:book="book"
:data="data"
></header-counter>
</div>
<script>
//子级元素
Vue.component('header-counter',{
data:function(){
return{
count:"想屁吃?"
}
},
props:["book","data"],
template:`
<div style="width: 100%;height: 200px;background-color: #38a1bf">
<h1>{{ book.title }}</h1>
<h3>{{ book.content }}</h3>
<p>{{ book.author }}</p>
<p>{{ book.date }}</p>
<p>{{ data.a }}</p>
<p>{{ count }}</p>
</div>
`
})
//父级元素
let app = new Vue({
el:"#app",
data:{
book:{
title:"红楼梦",
content:"万花丛中过,片叶不沾身",
author:"曹雪芹",
date:"2020年11月26日",
},
data:'',
},
mounted(){
this.data = this.getPost()
},
methods:{
getPost(){
let data = {a:"123",b:"456"}
return data
}
}
})
</script>
(2)prop
A. prop向组件传输数据
只需要在组件中标明哪些是需要传输的数据,写在属性props中就可以了。
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
调用组件时
<blog-post title="123"></blog-post>
B. 动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:message="parentMsg"></child>
</div>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
C. prop验证
prop一般是指父级给子级组件传输数据的方法。但有时候父级可能出现不正常的数据传输,这时候我们可以使用prop验证来方便我们对输入的数据进行判断,判断父级输入的数据是否正确。
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
实例
<div class="app">
<button-counter title="123" age="20"></button-counter>
</div>
<script>
let Child = {
data:function(){
return{}
},
props:{
title:String,
age:{
validator:function(value){
if(value > 18 && value < 50){
return true
}else{
return false
}
}
}
},
template:'<div>我今年{{ age }}岁,{{ title }}</div>'
}
new Vue({
el:".app",
components:{
"button-counter":Child,
}
})
</script>
6.Vue的自定义指令
除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。
下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:
<div class="app">
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-focus>
</div>
<script>
//注册一个全局自定义指令v-focus
Vue.directive('focus',{
//绑定元素插入到DOM中
inserted:function(el){ //inserted是一个函数,该函数的回调参数(el)就是绑定的元素对象
console.log(el) //输出<input>
el.focus() //聚焦元素
}
})
//创建根实例
new Vue({
el:".app",
})
</script>
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
-
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
-
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
-
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
-
unbind:只调用一次,指令与元素解绑时调用。
钩子函数参数
- el:指令所绑定的元素,可以用来直接操作 DOM。(原生JS的DOM当然也可以使用JQ把它包括起来方便一些方法的使用)
- binding:一个对象,包含以下 property:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
- vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。