一、前端框架是什么?
是js的工具集合,而不是HTML和CSS的工具集;前端发展好,是因为js决定了前端的发展前景
例如HTML5也需要借助于JS,只有把JS基础学好才能构建更好的前端项目。
二、为什么要用框架呢?
1、前端框架的基础都是JS,更好开发项目
遵循限定的条件,例如jQuery的$的规则,有更好的维护性、升级性和复用性,这些条件或者规则起个名叫:架构或者模式。现在的框架都是基于一个架构/模式的,例如MVVM、MVC、MVP模式等等,这些模式就是我们去使用框架的原因,可以更好开发项目的原因
2、更快开发项目
jQuery或者Vue都是组件化开发,其实组件化开发就是我们开发的必然。开发时很多组件是重复的,例如导航栏每次开发就浪费时间了。那么经常使用的东西把他封装成一个组件,下次再开发的时候直接拿来使用,直接调用组件,传参就行了,把时间放在核心业务上,把核心业务做好才能体现价值,这就是为什么要使用框架,更好更快开发项目
三、不要盲目使用框架
1、框架复杂度(学习成本,按照规则写代码,要学,学完规则后才能写)
2、应用复杂度(简单项目还是复杂项目,单页还是多页等等)
3、如果应用特别简单,没必要使用框架,使用原生就行了
四、三大主流框架
Vue Angular React
Angular---谷歌开发
问题:经常修改API和Tyscript
优势:开发思想好,依赖注入
Angular1---PC端,很重
Angular4、5---移动端
Tyscript语法,在js上又封装一层
React---FaceBook开发
优势:虚拟DOM---JS渲染快,DOM渲染慢,如果把DOM渲染变成JS渲染
问题:学习成本高,JSX 语法,把所有HTML和CSS都写在JS里面了
Vue---国产
优势:结合Angular和React的思想开发,有组件化、依赖注入、虚拟DOM、书写方法和以前一样,学习成本不高,兼容Tyscript,自由度高
五、Vue官网
1、渐进式JavaScript 框架:https://cn.vuejs.org/
2、Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器
3、Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库:http://element.eleme.io/#/
4、大型项目需要:Vuex状态管理:https://vuex.vuejs.org/zh-cn/
5、生态系统:https://github.com/vuejs/vue
6、单页面应用:vue-router,https://github.com/vuejs
8、论坛上不想等待的话有聊天室:https://discordapp.com/invite/HBherRA
六、Vue小例子
例1
<div id="app">
<h1>1、vue给我们用的第一种语法是{{}}</h1>
信息:{{ msg }}<br />
<!--模板语法,里面是js的变量,可写表达式:例如:age * 2-->
年龄:{{ age }}<br />
年龄:{{ age*2 }}<br />
年龄是否大于60岁:{{ age > 60 ? '老人' : '青年'}}<br />
第一个和最后一个名字:{{ firstName + " " + lastName }}<br />
类数组:{{ fullName.split(" ") }}<br />
类数组第2位:{{ fullName.split(" ")[1] }}<br />
方法this实现:{{ getFullName1() }}<br />
方法传参:{{ getFullName2(firstName,lastName) }}<br />
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app" ,//属性
data: {
msg: "Hello World",
age: 20,
lastName: "an",
firstName: "lin",
fullName: "lin an"
},
methods: {//方法,vue给我们提供好的
getFullName1: function () {
return this.firstName + " " + this.lastName
//第1种,利用this
//this就是代表app实例,app实例把app上面的属性全部挂在app最顶层,我们就能通过this.去获取到firstName和lastName
},
getFullName2: function (first,last) {
return first+ " " + last
//第2种:传参
},
getFullName3: (first,last) => {
return console.log(this.lastName);//这里的this就不是我们想要的
//第3种:es6 箭头函数
//不能用箭头函数
}
}
})
//app才是vue的实例
//app.msg可获取数据
//传的参数是一个对象
//通过new vue创建实例,并且控制了el后面属性选择的HTML代码,然后可以往这段HTML代码里去填充一个{{}}的语法
//{{}}的语法可以写一个js表达式,js表达式可以输出data里面的数据,并且可以对这个数据进行加工,假如说现在的一个数据非常复杂,假如需要一些逻辑判断和循环,
//我们可以写一个方法,那一个方法是怎么实现的呢?
//写一个方法和写一个变量是一样的,如果想定义一个数据定义一个变量的话,必须写在data的数据上面去
//假如在方法里面传参,可以通过this获取,也可以通过{{}}模板语法传把firstName参进去,firstName会去vue的data里面去取数据,只是利用函数调用的一个参数的形式传进去,那定义函数的时候就要写形参
//定义函数的时候要注意一个问题,如果es6定义了一个函数,箭头函数,箭头函数是没有this指向的,this指向是借助调用他那个作用域的this指向在vue底层操作不知道哪里去调用getFullName3,不知道的话他的this指向就会指向window,因为会有一个undefined
</script>
例2
<div id="app2">
<h1>2、vue给我们用的第二种语法是一个指令</h1>
<a v-bind:href="url">百度</a><br />
如果直接使用{{url}},那么会报错,要使用vue的,因为赋值的时候还是{{url}},href是一个属性,后面一定是一个字符串,后面解析成字符串,而不是解析成vue的语法,需要借助vue的指令,告诉我们这段DOM去做什么,现在绑定一个数据到属性上面去。<br />
v-bind:想绑定什么样的属性;后面等于一个表达式,表达式里面写想写的数据<br />
vue的指令,告诉我们这段DOM去做什么<br />
vue的指令语法:<br />
v-指令名字+:+指令的参数 = 指令的表达式<br />
例如:v-bind:href="url"<br />
</div>
<script type="text/javascript">
var app2 = new Vue({
el: "#app2",
data: {
url: "http://www.baidu.com"
}
})
</script>
例3
<div id="app3">
<h4>需求1:输出一个电影的名字和上映日期</h4>
电影名字:
上映日期:
<h4>需求2:判断一部电影是不是新电影,>2000年的就是新电影 不然就是旧电影</h4>
这部电影是 {{ getMovie() }} 电影
<h4>电影的名字title的绑定</h4>
<div v-bind:title = "movieTitle">
hover me
</div>
</div>
<script type="text/javascript">
var app3 = new Vue({
el: "#app3",
data: {
movieTitle: "红海行动",
movieDate: "2018"
},
methods: {
getMovie: function () {
return this.movieDate > 2000 ? '新' : '旧'
}
}
})
</script>
例4
<div id="app4" class="mar-b-30">
<h4 class="mar-b-10">点击事件 v-on:click="showsome"</h4>
<button v-on:click="showsome">第一种点击方式!</button>
<button v-on:click="showsome(1000,$event)">第二种点击方式!</button>
<h5 class="mar-t-30 mar-b-10">阻止事件冒泡-事件修饰符.stop</h5>
<div v-on:click="showsome(10,$event)">
<button v-on:click.stop="showsome(1000,$event)">点击事件冒泡!</button>
</div>
<h5 class="mar-t-30 mar-b-10">阻止默认事件-事件修饰符.prevent</h5>
<a href="http://www.baidu.com" v-on:click.prevent="showsome" class="btn">阻止默认事件,阻止默认跳转行为</a>
<div class="mar-t-10">
<a href="http://www.baidu.com" v-on:click.prevent class="btn">阻止默认事件,没有弹窗</a>
</div>
</div>
<script type="text/javascript">
var app4 = new Vue({
el: "#app4",
data: {},
methods: {
showsome: function (msg,event) {
console.log(msg);
alert("阻止事件冒泡-事件修饰符.stop")
}
}
})
</script>
例5
<div id="app5" class="mar-b-30">
<h3 class="mar-b-10">按键修饰符</h3>
<h4 class="mar-b-10">按键修饰符-.enter.space.esc.13(键盘号码),可以链式调用的</h4>
<h4 class="mar-b-10">系统修饰符-.shift//系统规定,shift必须和其他键一起按</h4>
<input type="text" v-on:keyup.enter.space="keyup" name="" id="" value="" />
<input type="text" v-on:keyup.shift="shift" name="" id="" value="shift必须和其他键一起按" />
<button v-on:click.shift="shift">按住shift+鼠标左键</button>
<button v-on:click.meta="meta">window键盘或者苹果的command</button>
</div>
<script type="text/javascript">
var app5 = new Vue({
el: "#app5",
methods: {
keyup: function(){
/*if(event.which == 13){
alert("按键了")//这是原生js的按enter键就弹出方法
}*/
alert("按键了")
},
shift: function(){
alert("shift必须和其他键一起按")
},
meta: function(){
alert("window键盘或者苹果的command")
}
}
})
</script>
例6
<div id="app6">
<h4 class="mar-b-10">按键修饰符例子</h4>
需求1:输入什么,输出什么,双向数据绑定<br />
<input type="text" v-on:keyup = "changeName"/>
<div>output: {{name}}</div><br />
需求2:和刚刚一样的,如果改变第二个输入框,但只要输入一个空格或者enter键盘才能把第一个输入的变量改变了
<br />
<input type="text" v-on:keyup.enter.space = "name = $event.target.value"/><br />
可以写简单的函数表达式或者语句
在HTML模板中通过name获取this里面的值
通过name获取this里面的name,当前input里面的值,通过事件对象获取,在HTML模板中怎么获取事件对象呢,vue给我们了一个方法$event.target.value
<div>output: {{name}}</div><br />
需求3:把form表单的默认提交的事件取消掉<br />
<form action="" v-on:submit.prevent="submitDefault">
<input type="submit"/>
</form>
</div>
<script type="text/javascript">
var app6 = new Vue({
el: "#app6",
data: {
name: "hello"
},
methods: {
changeName: function(event){
//获取input的name的话,可以使用原生的一个事件,event,系统默认会把默认的event传进来
this.name = event.target.value;
//如果想在methods里面获取数据的话,必须通过this.name指的是当前vue实例,因为他在底层会做一个数据绑定,作用域vue最顶层,可以通过this.name获取值
},
submitDefault: function(){
alert("阻止了表单提交")
}
}
})
</script>
<div id="app7" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">双向数据绑定的例子</h4>
<input type="text" v-bind:value = " value " v-on:input = " input "/>
<div>这里是输入框的输出值:{{ value }}</div>
<div>文本框,v-bind指令可以把js数据输入到DOM属性上,直接书写{{}}的话属性会变成字符串,所以是 v-bind:value(绑定哪个属性)</div>
<div>文本框,v-on:click事件</div>
</div>
<script type="text/javascript">
var app7 = new Vue({
el: "#app7",//对象传,vue控制哪段html
data: {
value: "双向数据绑定的例子"
},
methods: {
input: function(event){
this.value = event.target.value
//数据变成我们输入的东西
//input函数会借助参数,是一个事件对象event
//this获取data里面的数据,data里面的数据在vue的底层会把他挂载到vue的实例的最顶层上去
}
}
})
</script>
<div id="app8" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">简化app7的双向数据绑定</h4>
<h5>双向数据绑定:首先把value输入到input框的value属性上面去了,用value把input框初始化了,并且我们写了一个事件,
事件的作用是改变HTML模板从而改变js里面代码,其实v-bind和v-on可以一起结合起来去看,
怎么结合呢,v-bind是把js里面的数据给输出到了DOM节点上去,那v-on就是DOM节点上的一些改变,
相当于用户操作的是一个用户节点,在input里面输入, 操作DOM节点从而改变js里面的数据,
他两是一个相反的过程,如果两步都实现,这就是双向数据绑定,如果按照app7这样写会很麻烦,如果想有一个简单简便的写法,
因为这样的一个需求在我们日常开发中也是很多的,那么就有一个指令叫v-model 后面绑定的就是数据,这就实现了刚才app7的两步,
methods方法也就不需要了,<br />
第一步就是把value绑定到input的value的属性上去,所以初始化值就是:“简化双向数据绑定的例子”<br />
第二步,就是每改变input的DOM上输入的值,就会把{{}}中的value的值改变,也就是利用v-model的指令实现了两步操作,一个叫v-bind,一个是v-on<br />
使用了v-model的话,在input里面再写一个value的话就不好使了。会把value覆盖了<br />
v-model也有修饰符,v-bind绑定一个事件的时候,都已经提到,修饰符可以让你更方便做常做的事情,例如事件修饰符.prevent就可以阻止默认事件<br />
.stop就能阻止事件冒泡,例如按键的时候,想输入特定的按键才会触发事件,例如.enter就是通过按一个enter键,才会触发这个事件,还有一些系统按键的修饰符,
contrl,shift键等等<br />
还有一些苹果的command键,window上的window键
</h5>
<input type="text" v-model = " value "/>
<div>这里是输入框的输出值:{{ value }}</div>
<div>v-mode = " 简化双向数据绑定的例子 "</div>
</div>
<script type="text/javascript">
var app8 = new Vue({
el: "#app8",//对象传,vue控制哪段html
data: {
value: "简化双向数据绑定的例子"
}
})
</script>
<div id="app9" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">v-model事件修饰符.trim</h4>
<input type="text" v-model.trim = " value "/>
<div>这里是输入框的输出值:{{ value }}</div>
<h5>
v-model.trim = " " .trim修饰符<br />
js里的trim的作用是把首尾的空格去掉<br />
现在如果加上v-model的事件修饰符.trim,那么,当文本中有包含2个空格以上的时候,在value中就只显示一个空格<br />
</h5>
</div>
<script type="text/javascript">
var app9 = new Vue({
el: "#app9",
data: {
value: "v-model事件修饰符"
}
})
</script>
<div id="app10" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">v-model事件修饰符.number</h4>
<input type="text" v-model.number = " value "/>
<div>这里是输入框的输出值:{{ value }}</div>
<h5>
v-model.number = " " .number修饰符<br />
.number修饰符会把{{ value }}上面输出的所有数据全部变成一个数字<br />
如果没有加上.number修饰符-----检查输出的20 是不是字符串还是数字,可以使用typeof返回的是:{{ typeof value }}类型<br />
但是当我们清掉input里面的数据的话,再输入就变成string类型了,因为我们在input里面输入的东西全部都是srting字符串,所以返回字符串。<br />
如果加上.number修饰符-----那么类型就始终都是number,因为会自动把输出的改成数字。
</h5>
</div>
<script type="text/javascript">
var app10 = new Vue({
el: "#app10",
data: {
value: 20
}
})
</script>
<div id="app11" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">v-model事件修饰符.lazy</h4>
<input type="text" v-model.lazy = " value "/>
<div>这里是输入框的输出值:{{ value }}</div>
<h5>
v-model.lazy = " " .lazy修饰符<br />
如果没有加.lazy修饰符,那么我们双向数据绑定时候,每在input输入时,都会改变大括号里的value值<br />
如果加.lazy修饰符,那么数据将会在鼠标移出输入框的时候才会改变<br />
js可以改变dom,dom可以改变数据-----双向数据绑定
</h5>
</div>
<script type="text/javascript">
var app11 = new Vue({
el: "#app11",
data: {
value: "如果加.lazy修饰符,那么数据将会在鼠标移出输入框的时候才会改变"
}
})
</script>
<div id="app12" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">HTML操作</h4>
<div>输出值:{{ html }}</div>
<div>会重新渲染:{{ message }}</div>
<div v-once>加了v-once不会重新渲染:{{ message }}</div>
<button v-on:click = "message = '123'">点击我,改变上一行,响应式的数据绑定</button>
数据会重新渲染,DOM也会重新渲染,
<h5>
数据一般是字符串格式,如果想把数据渲染成DOM节点的话?想把DOM节点输出到双括号中<br />
输出的是字符串,有两个好处<br />
1、防止跨域脚本攻击-------假如说在HTML中输出的是一个DOM节点,如果直接按照DOM节点输出的话,假如说有一个黑客把这个页面拦截了,HTML和JS都是以明码的方式给你的,就可以把服务器的js和HTML全部下载到本地浏览器运行。那既然是一个明码的方式,读取到你的js里面知道你是Vue去写的,并且知道你的HTML里面的数据是DOM节点,完全可以把DOM节点换成script标签,换成script标签之后,在本地浏览器里面一运行script把你本地的信息全部发送发到他的服务器里面去,这就是xss跨域的脚本工具,所以说使用DOM是很危险的行为<br />
2、防止用户随意更改DOM-----如果用户,利用input框输入一个DOM节点,那用户可以随意地更改你页面里面的东西,比如说这个页面是不可控的,你不知道用户会把你页面变成什么样子,这样的行为也是不好的<br />
所以把输出的变成是默认的字符串<br />
解决问题:-----通过指令<br />
<div v-html = "html"></div>
如果使用了v-html,既然他的默认行为就是想让你去输出字符串,就一定一定要注意数据是安全的,不能让用户去随意修改,而且必须是隐藏好的,不能有一个轻易的脚本跨域攻击。一定要慎重选用
如果说我们现在有一个数据绑定,有个数据,我们每一次改变数据,HTML都统一渲染,那假如说就想只渲染初始化,剩下的如果我们改变了数据,我们不想在渲染了,也用到一个指令<strong>v-once</strong><br />
</h5>
</div>
<script type="text/javascript">
var app12 = new Vue({
el: "#app12",
data: {
html: "<h1>hello</h1>",
message: "linsheng"
}
})
</script>
<div class="app13" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">指令v-if用于条件判断的</h4>
<div>
<div>如果大于10,显示有现货,如果小于10,显示所剩不多,如果0,显示没库存</div>
<p v-if = " items > 10">输出:{{ items }}个有现货</p>
<p v-else-if = " items > 1">输出:所剩不多了,快点买</p>
<p v-else>输出:没库存了</p>
</div>
<h5>
可能有很多DOM节点。在不同条件下只渲染一部分DOM节点,假如说有一个input,input右边可能有一个DOM节点,来显示输入的用户名是否正确,如果正确,DOM节点是正确,否则相反,可能写了两个DOM节点,一个是正确,一个是错误的,只不过根据用户输入的正确或者错误给不同的DOM渲染出来,现在用Vue实现<br />
</h5>
</div>
<script type="text/javascript">
var app13 = new Vue({
el: ".app13",
data: {
items: 5
}
})
</script>
<div id="app14" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">正常的话,渲染出的是linjian,那当网络不正常,DOM结构加载完之后,下面的vue.js还没加载过来或者被阻塞了,即vue实例创建失败,返回的就是{{ message }}</h4>
<div>
<div>
刷新页面后等待3秒后出现信息:{{ message }}
</div>
<div v-clock>
<h4>直接就写v-clock就行了,就是当加载完vue实例,把他变成HTML模板之后,即加载完DOM后,v-clock指令就消失了</h4>
刷新页面后等待3秒后出现信息:{{ message1 }}
</div>
<h5></h5>
</div>
<!--<script src="resources/js/vue.js"></script>-->
</div>
<script type="text/javascript">
//模拟一个异步,模拟的意义就是,等vue加载完之后才会执行3秒之前都是{{}}的形式,3秒之后就刷新数据了
setTimeout(function(){
var app14 = new Vue({
el: "#app14",
data: {
message: "linjian",
message1: "11111111111",
}
})
},3000);
</script>
<div id="app15" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">所有的DOM操作都能用vue去做,vue用的是vue指令实现</h4>
<h4 class="mar-b-10">循环:v-for=""</h4>
<h4 class="mar-b-10"><strong>语法:v-for="别名 in 表达式"</strong>,别名是任意起的一个变量名,例如现在的movies</h4>
<h4 class="mar-b-10">v-for="title in movies",意思就是循环下面的数组,有多少个就循环多少次,每一次循环都有个变量,如title,就是变量的别名</h4>
<div class="mar-b-10">
<div><strong>案例1、循环一个数组的方法------------------------下面输出的是电影列表</strong></div>
<ol>
<li v-for="title in movies">{{ title }}</li>
</ol>
</div>
<div class="mar-b-10">
<div><strong>案例2、循环一个数组------------------------需要知道数组的索引是什么</strong></div>
<h4 class="mar-b-10"> v-for="(title,index) in movies",后面使用小括号加索引index,其中的index也是我们给的变量,些什么后面就用什么</h4>
<ol>
<li v-for="(title,index) in movies">{{ title }}({{ index }})</li>
</ol>
</div>
<div class="mar-b-10">
<div><strong>案例3、循环一个复杂的数组,输出一个员工列表和职位,通过对象的属性来处理</strong></div>
<div class="mar-b-10"><strong>其中公司名就是告诉我们,v-for="" 里面也能使用正常的数据绑定</strong></div>
<table border="">
<thead>
<tr>
<th>员工姓名</th>
<th>员工职位</th>
<th>所在公司</th>
</tr>
</thead>
<tbody>
<tr v-for="person in persons">
<td>{{ person.name }}</td>
<td>{{ person.title }}</td>
<td>{{ company }}</td>
</tr>
</tbody>
</table>
<h4>有索引的案例</h4>
<table border="" class="mar-b-10">
<thead>
<tr>
<th>员工姓名</th>
<th>员工职位</th>
<th>所在公司</th>
<th>索引</th>
</tr>
</thead>
<tbody>
<tr v-for="(person,index) in persons">
<td>{{ person.name }}{{index}}</td>
<td>{{ person.title }}{{index}}</td>
<td>{{ company }}</td>
<td>{{index}}</td>
</tr>
</tbody>
</table>
<h4><strong>案例4、循环对象,v-for=""的特殊用法,只用name的话循环出来的是所有对象的属性值,如果要对象的属性名,(name, prop),prop就是属性名</strong></h4>
<div v-for="name in person" class="mar-b-10">
{{ name }}
</div>
<h4>键值对的方式输出</h4>
<div v-for="(name,prop) in person">
{{ prop }} : {{ name }}
</div>
<h4 class="mar-t-10">键值对的方式输出--------带索引值</h4>
<div v-for="(name,prop,index) in person">
{{ prop }} : {{ name }}({{index}})
</div>
<h4><strong>案例5、v-for数字循环,输出的是1-3,v-for="n in 3"</strong></h4>
<div class="mar-b-10"><div v-for="n in 3">没有索引值的循环{{ n }}</div></div>
<div v-for="(n,index) in 3">有索引值的循环{{ n }},当前索引值是:{{ index }}</div>
<h4><strong>案例6、v-for字符串循环,输出的是每个字符串,v-for="s in 'lin'"</strong></h4>
<div class="mar-b-10"><div v-for="s in 'lin'">{{ s }}</div></div>
<div v-for="(s,index) in 'lin'">{{ s }},当前索引值是:{{ index }}</div>
<h4 class="mar-t-10"><strong>v-for=""使用注意事项------循环一个数组需要注意的地方</strong></h4>
<h4 class="mar-b-10">数组是一个引用值,引用值指向内存空间,假如把numbers里面的2变成10,但还是以前的那个地址,那个内存空间,并没有变地址,那vue通过,object.property进行数据绑定,内存地址没变,就不会触发vue的set,就不会触发DOM节点的渲染,所以现在看起来还是以前的数,2.数组的值改变了,但是索引没有改变,因此,就不会重新渲染我们的DOM节点</h4>
<ul>
<li v-for="n in numbers">{{ n }}</li>
</ul>
<button v-on:click="changeNumber" class="mar-b-10">点击修改第2个数变成10,发现没变</button>
<h4 class="mar-b-10">点击修改第2个数变成10,非要改变,就要用vue内部的set方法实现,如果以set方法进行设置,就会对DOM节点进行渲染。这个就是vue的内部机制,也是js的一个缺陷,无法检测数组里面元素的变化,因为只是检测内存地址的变化,如果地址没有变化,就认为没有变化。</h4>
<h4>Vue.set(想设置谁,索引,设置值)有三个参数,如:Vue.set(this.numbers,1,10)</h4>
<ul>
<li v-for="n in numbersOk">{{ n }}</li>
</ul>
<button v-on:click="changeNumberOk">点击修改第2个数变成10,非要改变</button>
<h4 class="mar-b-10 mar-t-10"></h4>
<h4 class="mar-b-10">push方法添加一组数据,按照上面的例子,一直往数据添加数据,vue能检测到数组内部的变化,并且把他渲染出来,重新渲染DOM。就是vue底层的操作:把js底层的push方法进行了重写,虽然看到的是push方法,但是跟我们看到的数组方法的push方法已经不一样了,使用了观察者模式</h4>
<h4 class="mar-b-10"><strong>v-for运行机制:模板复用机制</strong></h4>
<h4>直接把上一个模板拿过来接着使用,就不用重新渲染DOM了,从而节省性能,但是会有bug</h4>
<h4>重写的数组方法有:push,por,shift,unshift,sort,reverse,splice</h4>
<ul class="mar-b-10">
<li v-for="item in listItem">
{{item.id}}、
{{item.name}}
{{item.time}}
</li>
</ul>
<button v-on:click="addGroup">点击我添加一组数据</button>
<button v-on:click="reverse">reverse把数组倒置</button>
<h4 class="mar-b-10 mar-t-10"><strong>下面这个例子会有问题了,点击后倒置,只有前面的会倒置,后面的input框没有倒置了,因为现在用的是同一套模板,三个input框识别成了一个,所有的都是一样的input框,就不用DOM渲染,也就不会倒置,过滤掉了</strong></h4>
<h4>如果现在想让他进行渲染,可以给一个key值,告诉模板这个input框是独一无二的,不是一样的。v-bind:key="item.id"</h4>
<h4>那么第一个模板的key是1,第二个是2。。。。并且提到了2点:</h4>
<h4>第一点:v-for是需要知道数组或者对象里面的name元素的变化不会引起DOM渲染,如果我们想要让DOM进行渲染,就用Vue.set()设置属性或者重写后的数组方法去写</h4>
<h4>第二点:v-for=""进行了循环,用了一个模板复用的思想,比如说所有模板是一样的话,就不会重新渲染DOM,如果想让他每次改变DOM都让他从新渲染DOM的话,就给一个独一无二的key值,vue就知道这些是不一样的,就会重新渲染DOM节点</h4>
<ul class="mar-b-10">
<li v-for="item in listItem" v-bind:key="item.id">
{{item.id}}、
{{item.name}}
{{item.time}} <input type="text" />
</li>
</ul>
</div>
</div>
<script type="text/javascript">
var app15 = new Vue({
el: "#app15",
data: {
numbers: [1,2,3,4],
numbersOk: [0,1,2,3],
movies: ["黑豹","复仇者联盟","至暗时刻"],
persons: [{
name: "林",
title: "web前端"
},{
name: "张",
title: "UI设计"
},{
name: "赵",
title: "Java后台"
}],
company: "阿里巴巴",
person: {
lastName: "林",
firstName: "先生",
age: 10
},
listItem: [{
id: 1,
name: "林",
time: 2016
},{
id: 2,
name: "钱",
time: 2017
},{
id: 3,
name: "孙",
time: 2018
}]
},
methods: {
changeNumber: function(){
this.numbers[1] = 11
alert("应该弹出来是一个"+ this.numbers[1] + "但却没有修改成功,因为是引用值")
},
changeNumberOk: function(){
Vue.set(this.numbersOk , 1 , 10);
alert("应该弹出来是一个"+ this.numbersOk[1])
},
addGroup: function(){
this.listItem.push({
id: 4,
name: "周",
time: 2019
})
},
reverse: function(){
this.listItem.reverse()
}
}
})
</script>
<div id="app16" class="mar-t-30 mar-b-30">
<h4 class="mar-b-10">案例7、</h4>
<h4 class="mar-b-10">
<p>1、双向数据绑定案例</p>
<input type="text" v-model="textInput"/>
<p>{{ textInput }}</p>
在这要注意,这里如果是input或者password框,就绑定到value上面去。去过是复选框上的话,就绑定check上。如果是check是true是选中状态,否则就是未选中状态
</h4>
<div class="mar-b-10">
<div>2、v-if v-else-if else用法案例</div>
<p v-if="numbers > 5">你的数字大于5</p>
<p v-else-if="numbers > 3">你的数字大于3</p>
<p v-else>你的数字小于3</p>
</div>
<div class="mar-b-10">
<h2><strong>3、v-for=""循环里面再循环</strong></h2>
<ol>
<li v-for="box in subs">
{{ box.name }}
<ul>
<li v-for="arr in box.sub">{{ arr }}</li>
</ul>
</li>
</ol>
</div>
</div>
<script type="text/javascript">
var app15 = new Vue({
el: "#app16",
data: {
textInput: "这个是一个双向数据绑定的案例",
numbers: 8,
subs: [{
name: "HTML",
sub: ["div","p","a"]
},{
name: "Css",
sub: ["css1","css2","css3"]
},{
name: "Javascript",
sub: ["Jquery","Vue","Angular"]
}]
}
})
</script>
v-bind
缩写::
预期:any (with argument) | Object (without argument)
参数:attrOrProp (optional)
修饰符:
.prop - 被用于绑定 DOM 属性。
.camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase.
.sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
用法:
动态地绑定一个或多个特性,或一个组件 prop 到表达式。
在绑定 class 或 style 特性时,支持其它类型的值,如数组或对象。
在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。
没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。
v-bind缩写: : 如 :src="item.imgPath" ==> v-bind:src="item.imgPath"
v-on
缩写:@
预期:Function | Inline Statement | Object
参数:event
修饰符:
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
用法:
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
从 2.4.0 开始,v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。
用在普通元素上时,只能监听 原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性:v-on:click="handle('ok', $event)"