vue学习笔记—vue基础(二)
参数设置
从一个Vue的实例开始的
使用Vue创建一个应用的时候,需要传入一些必要的配置参数
参考:api -> 选项
选项包含分类:
- 1.数据
如: data : 设置vue的数据(观察数据),vue应用中所需要使用的数据可以放置在该选项中,同时vue会监听和观察data中的变化;
放置应用中所需要使用到的元数据,开始就能确定的数据
methods: 保存vue应用中所需要使用到函数 -
- DOM
如:el : 设置vue应用根节点
- DOM
-
- 生命周期钩子函数
-
- 资源
-
- 组合
-
- 其他
相关概念
- 视图
我们看到的页面 - 模板
- 产生页面的结构
模板语法:把实例中的数据和页面进行绑定的一种手段
- 插值表达式
- {{表达式}} => 大胡子语法
- 注意:该语法是解析安全的(因为会将数据做为纯文本解析,防止xss)
XSS:
xss:跨站脚本攻击(Cross Site Scripting)。。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
- 插值表达式
(1) vue内部对大通过胡子语法使用的数据做文本解析,其内部实现原理:
<code>
<textarea id="content" cols="30" rows="10"></textarea>
<ul></ul>
<!--<p>
<span>aaaa</span>
©
</p>-->
<script>
var content = document.querySelector('#content');
var ul = document.querySelector('ul');
content.onblur = function() {
var li = document.createElement('li');
<!--将用户提交的数据先进行处理,将HTML标签中的“<”和“>”替换成HTML实体字符,
这样浏览器就不会误将它认为是HTML标签。处理完之后,再将用这些数据展示在页面。-->
li.innerHTML = content.value.replace(/<|>/g, ($0) => {
if ($0 == '<') {
return '<'
}
if ($0 == '>') {
return '>'
}
});
ul.appendChild(li);
}
</script>
</code>
HTML实体字符
以实体代替与HTML语法相同的字符,避免浏览解析错误。
(2) 差值表达式的纯文本解析与v-html。
<code>
<div id="app">
<div>{{content}}</div>
<div v-html="content"></div>
<img src="{{logo}}" />//报错
<img v-bind:src="logo" />
<img v-bind:src="'http://miaov.com/static/normal/images/index/mLogo.' + 'png'" alt="">
</div>
<script>
var app = new Vue({
el: '#app',
data: {
title: '打招呼',
content: '<p>大家好!http://www.baidu.com</p>',
logo: 'http://miaov.com/static/normal/images/index/mLogo.png'
}
});
</script>
</code>
注意:
<div>{{content}}</div>
渲染到页面是”<p大家好!http://www.baidu.com</p>
“;而对于<div v-html="content"></div>
来说,渲染到页面是 “大家好!http://www.baidu.com”,即p标签被解析了。“
<img src="{{logo}}" />
“这样写会报错,“src=”{{logo}}”: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of<div id="{{ val }}">
, use.”
指令
- 概念:
- 是一个 v- 前缀的特殊属性,指令的使用方式是以html标签属性形式存在的
- 指令有对应的值,值是以表达式的形式存在的
- 指令的作用:根据指令的值动态的影响指令所在的html标签的表现与行为
- vue中所有内置指令: api-指令
指令:
- v-text:更新元素的文本内容(数据解析出来是纯文本),相当于差值表达式的作用
<h2 v-text="'标题是:' + title"></h2>
,相当于{{title}}。 - v-html:更新元素的 innerHTML。
关于v-text,差值表达式与v-html的区别,上文中的例子可以说明。 - v-show:
<h2 v-show="false">大家好</h2>
根据表达式之真假值,切换元素的 display CSS 属性。
v-if:如果表达式的值为false,该元素就不存在(HTML结构不存在)
<h2 v-if="true">大家好2</h2>
根据表达式的值的真假条件渲染元素。
v-for
列表渲染:
- (1) 数组或字符串的v-for:
- 第一个参数:item 是数组元素迭代的别名;
- 第二个参数:当前项的索引。
<li v-for="v,k in 'miaov'">{{v}} - {{k}}</li>
- (2) 对象的v-for:
- 第一个参数:item是对象键值迭代的别名;
- 第二个参数:当前键值对应的键名;
- 第三个参数:当前项的索引。
<li v-for="v,k,i in {left:100,top:200}">{{v}} - {{k}} - {{i}}</li>
(3) key
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的且唯一的 id。
建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。<code> <button @click="sort">排序</button> <ul id="list"> //用 v-bind 来绑定key动态值 (在这里使用简写) <li :class="v" v-for="v,k in arr" :key="k">{{v}} -- {{k}}</li> </ul> </code>
- (1) 数组或字符串的v-for:
- (4) 数组更新检测
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
(1) 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
解决方案:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)
(2) 当你修改数组的长度时,例如:vm.items.length = newLength
解决方案:
example1.items.splice(newLength);
- v-text:更新元素的文本内容(数据解析出来是纯文本),相当于差值表达式的作用
v-on:
- 参数:event,事件名;
修饰符:
- 写法:
(1) 指令.修饰符;
(2) 指令:参数.修饰符 修饰符举例:
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
(1)<button @click.stop="fn2" @contextmenu.prevent>按钮</button>
(2)<code> <div @click.self="fn1"> <!--阻止所有子元素冒泡到父级,不用为每个子元素阻止冒泡, 而可用修饰符“.self”,让该事件绑定父元素本身 --> <!--<button @click.stop>按钮</button>--> <!--<button @click.stop>按钮</button>--> <!--<button @click.stop>按钮</button>--> <!--<button @click.stop>按钮</button>--> <!--<button @click.stop>按钮</button>--> <button>按钮</button> <button>按钮</button> <button>按钮</button> <button>按钮</button> <button>按钮</button> <!--串联修饰符,".enter" ,回车键的别名--> <input type="text" @keydown.enter.32="input"> </div> </code>
- 写法:
缩写:
在vue中,有且仅有两种指令可缩写:
(1)<button v-on:click="sort">排序</button>
==><button @click="sort">排序</button>
(2)<li v-bind:class="v">
==><li :class="v">
事件函数的参数
- 不带括号,默认为传入event(事件对象);
带括号,那么就表示当前函数需要接收event以外的参数,那这个时候需要手动传入event:$event.
<code> <!--不带括号,默认为传入event--> <button @click="fn">按钮</button> <!--带括号,那么就表示当前函数需要接收event以外的参数, 那这个时候需要手动传入event:$event--> <button @click="fn($event, 1, 2)">按钮</button> var app = new Vue({ el: '#app', data: {...}, methods: { fn(e, a, b) { console.log(e); }, } }) </code>
- v-model:
- 在表单控件元素上创建双向数据绑定;
- 它会根据控件类型自动选取正确的方法来更新元素。
- 会忽略所有表单元素的 value、checked、selected 特性的初始值。
- 修饰符:
- .lazy - 取代 input 监听 change 事件;(默认是onInput事件)
- .number - 输入字符串转为数字
- .trim - 输入首尾空格过滤
<input type="text" v-model.number="product.num" />
观察者和计算属性
- watch: 监听的数据变化,改变其他数据;
computed:计算属性,一般这里设置的值是根据某种条件获取到的数据,这里属性都是通过函数来描述的,
完整写法,类似Object.defineProperty方法:
<code> computed:{ 属性名:{ get(){}, set(){} } } </code>
在实际使用过程中,get比set要多很多,所以为了简化书写,可以不写对象形式的get和set
由于set(){}可能没有,就可简写成“属性名:function(){}
”,再精简就变成:属性名(){}
。
(1)get方法:根据其他数据变化,得到当前数据
(2) set方法:相当于watch方法,监听当前的数据变化,改变其他数据;<code> <body> <div id="app"> <table border="1" width="100%"> <thead> <tr> <th> <input type="checkbox" v- model="isCheckedAll">全选 </th> <th>名称</th> <th>单价</th> <th>数量</th> <th>小计</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="product in products"> <td> <input type="checkbox" v- model="product.checked"> </td> <td>{{product.name}}</td> <td>¥{{product.price.toFixed(2)}}</td> <td> <button @click="sub(product)">-</button> <input style="width: 50px;text-align: center" type="text" v-model.number="product.number"> <button @click="plus(product)">+</button> </td> <td>¥{{product.number * product.price}}</td> <td>操作</td> </tr> </tbody> </table> <h2>您一共购买了 {{totalSum}} 件商品,总价是:¥{{totalPrice}}</h2> <button v-bind:disabled="totalSum<=0">支付</button> </div> <script src="js/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { products: [ { name: 'iphone8', price: 8888.00, number: 0, checked: false }, { name: 'imac', price: 18666.00, number: 0, checked: false } ] }, methods: { plus(product) { product.number++; }, sub(product) { if (product.number >0 ) { product.number--; } } }, // watch: { //监听的数据变化改变其他数据 // isCheckedAll() { // console.log(1); // // this.products.forEach( (product) => { // // product.checked = this.checkedAll; // // } ); // } // }, // 计算属性,一般这里设置的值是根据某种条件获取到的数据, //这里属性都是通过函数来描述的, computed: { isCheckedAll: { //监听其他数据的变化,修改当前属性 get() { return this.products.filter( product => { return product.checked; } ).length == this.products.length; }, set(newValue) { this.products.forEach( (product) => { product.checked = newValue; } ); } }, totalSum() { var sum = 0; this.products.forEach( product => { if (product.checked) { sum += product.number; } } ); return sum; }, totalPrice() { var price = 0; this.products.forEach( product => { if (product.checked) { price += product.price * product.number; } } ); return price; } } }) </script> </body> </code>