<body>
<!-- 将来 new 的Vue实例,会控制这个 元素中的所有内容 -->
<!-- Vue 实例所控制的这个元素区域,就是我们的 V -->
<div id="app">
<p>{{ msg }}</p>
</div>
<script>
// 2. 创建一个Vue的实例
// 当我们导入包之后,在浏览器的内存中,就多了一个 Vue 构造函数
// 注意:我们 new 出来的这个 vm 对象,就是我们 MVVM中的 VM调度者
var vm = new Vue({
el: '#app', // 表示,当前我们 new 的这个 Vue 实例,要控制页面上的哪个区域
// 这里的 data 就是 MVVM中的 M,专门用来保存 每个页面的数据的
data: { // data 属性中,存放的是 el 中要用到的数据
msg: '欢迎学习Vue' // 通过 Vue 提供的指令,很方便的就能把数据渲染到页面上,程序员不再手动操作DOM元素了【前端的Vue之类的框架,不提倡我们去手动操作DOM元素了】
}
})
</script>
</body>
{{ }}
插值表达式会出现闪烁问题,即在网速慢时会出现{{ msg }}
,数据加载好后才会显示数据
v-bind
:
:title="btnTitle + '追加内容'"
<div id="app">
<input type="button" value="按钮" v-bind:title="mytitle + '123'">
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
mytitle: '这是一个自己定义的title'
},
})
</script>
v-on
@
<div id="app">
<input type="button" value="按钮" v-on:click="show">
</div>
<script>
var vm = new Vue({
el: '#app',
methods: {
// 这个 methods属性中定义了当前Vue实例所有可用的方法
show: function () {
alert('Hello')
}
}
})
</script>
分析:
代码:
<div id="app">
<input type="button" value="浪起来" @click="lang">
<input type="button" value="低调" @click="stop">
<h4>{{ msg }}</h4>
</div>
<script>
// 在 VM 实例中,如果想要获取 data 上的数据,或者 想要调用 methods 中的 方法,
// 必须通过 this.数据属性名 或 this.方法名 来进行访问,
// this表示 new 出来的 VM 实例对象
var vm = new Vue({
el: '#app',
data: {
msg: '猥琐发育,别浪~~!',
intervalId: null // 在data上定义 定时器Id
},
methods: {
lang() {
if (this.intervalId != null) return; // 防止多次点击按钮,创建多个定时器
// =>箭头函数解决了this的指向问题,如果不加,则this指向的是setInterval方法
this.intervalId = setInterval(() => {
var start = this.msg.substring(0, 1)
// 获取到 后面的所有字符
var end = this.msg.substring(1)
// 重新拼接得到新的字符串,并赋值给 this.msg
this.msg = end + start
}, 400)
// VM实例监听自己身上 data 中的数据,只要数据改变,就会自动把最新的数据,同步到页面中去
// 【好处:程序员只需要关心数据,不需要考虑如何重新渲染DOM页面】
},
stop() { // 停止定时器
clearInterval(this.intervalId)
// 每当清除了定时器之后,需要重新把 intervalId 置为 null
this.intervalId = null;
}
}
})
</script>
stop和self在阻止冒泡时的区别:
<div id="app">
<input type="text" v-model="n1">
<select v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" v-model="n2">
<input type="button" value="=" @click="calc">
<input type="text" v-model="result">
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
n1: 0,
n2: 0,
result: 0,
opt: '+'
},
methods: {
calc() { // 计算器算数的方法
// 逻辑:
switch (this.opt) {
case '+':
this.result = parseInt(this.n1) + parseInt(this.n2)
break;
case '-':
this.result = parseInt(this.n1) - parseInt(this.n2)
break;
case '*':
this.result = parseInt(this.n1) * parseInt(this.n2)
break;
case '/':
this.result = parseInt(this.n1) / parseInt(this.n2)
break;
}
// 注意:这是投机取巧的方式,正式开发中,尽量少用
// var codeStr = 'parseInt(this.n1) ' + this.opt + ' parseInt(this.n2)'
// this.result = eval(codeStr)
}
}
});
</script>
<h1 :class="['red', 'thin']">这是一个邪恶的H1</h1>
<h1 :class="['red', 'thin', isactive?'active':'']">这是一个邪恶的H1</h1>
// 三元表达式isactive?'active':''
// 其中isactive是判断条件,如果为true,则执行?后面的否则执行:后面的
<h1 :class="['red', 'thin', {'active': isactive}]">这是一个邪恶的H1</h1>
// 'active'是style中的类名,isactive是vm实例中data中的变量
<h1 :class="{red:true, italic:true, active:false, thin:true}">这是一个邪恶的H1</h1>
:style
的形式,书写样式对象<h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>
// 属性中有-时必须加引号
data
中,并直接引用到 :style
中data: {
h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
}
<h1 :style="h1StyleObj">这是一个善良的H1</h1>
:style
中通过数组,引用多个 data
上的样式对象data: {
h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
h1StyleObj2: { fontStyle: 'italic' }
}
<h1 :style="[h1StyleObj, h1StyleObj2]">这是一个善良的H1</h1>
<ul>
<li v-for="(item, i) in list">索引:{{i}} --- 姓名:{{item.name}}</li>
</ul>
<!-- 循环遍历对象身上的属性 -->
<div v-for="(val, key, i) in userInfo">{{val}} --- {{key}} --- {{i}}</div>
<p v-for="i in 10">这是第 {{i}} 个P标签</p>
2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的。
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
注意:
:key="item.id"
<h3 v-if="flag">这是用v-if控制的元素</h3>
<h3 v-show="flag">这是用v-show控制的元素</h3>
// flag等于true时标签显示,否则不显示
一般来说,v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好。
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class="panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name">
</label>
<!-- 在Vue中,使用事件绑定机制,为元素指定处理函数的时候,如果加了小括号,就可以给函数传参了 -->
<input type="button" value="添加" class="btn btn-primary" @click="add()">
<label>
搜索名称关键字:
<input type="text" class="form-control" v-model="keywords">
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<!-- 之前, v-for 中的数据,都是直接从 data 上的list中直接渲染过来的 -->
<!-- 现在, 自定义了一个 search 方法,同时,把搜索的关键字通过传参的形式,传递给了 search 方法 -->
<!-- 在 search 方法内部,通过 执行 for 循环, 把所有符合 搜索关键字的数据,保存到一个新数组中,再返回 -->
<tr v-for="item in search(keywords)" :key="item.id">
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td>{{ item.ctime }}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
keywords: '', // 搜索的关键字
list: [
{id: 1, name: '奔驰', ctime: new Date()},
{id: 2, name: '宝马', ctime: new Date()}
]
},
methods: {
add() {
// 1. 从data中取出id和name并组成一个对象
// 2. 把这个对象,添加到 data 上的 list 中
// 注意:Vue已经实现了数据的双向绑定,每当修改了 data 中的数据,Vue会默认监听到数据的改动,自动把最新的数据,应用到页面上;
var car = {id: this.id, name: this.name, ctime: new Date()}
this.list.push(car)
// 将input标签内的内容清空
this.id = this.name = ''
},
del(id) { // 根据Id删除数据
// 分析:
// 1. 如何根据Id,找到要删除这一项的索引
// 2. 如果找到索引了,直接调用 数组的 splice 方法
// 方法一,使用数组的some方法
/* this.list.some((item, i) => {
if (item.id == id) {
this.list.splice(i, 1)
// 在 数组的 some 方法中,如果 return true,就会立即终止这个数组的后续循环
return true;
}
}) */
// 方法二,使用数组的findIndex方法
var index = this.list.findIndex(item => {
if (item.id == id) {
return true;
}
})
this.list.splice(index, 1)
},
keywords
属性
v-for
指令循环每一行数据的时候,不再直接 item in list
,而是 in
一个 过滤的methods 方法,同时,把过滤条件keywords
传递进去
search
过滤方法中,使用 数组的 filter
方法进行过滤:
search(keywords) { // 根据关键字,进行数据的搜索
// 方法一
/* var newList = []
this.list.forEach(item => {
if (item.name.indexOf(keywords) != -1) {
newList.push(item)
}
})
return newList */
// 注意: forEach some filter findIndex 这些都属于数组的新方法,
// 都会对数组中的每一项,进行遍历,执行相关的操作;
// 方法二
return this.list.filter(item => {
// if(item.name.indexOf(keywords) != -1)
// 注意 : ES6中,为字符串提供了一个新方法,叫做 String.prototype.includes('要包含的字符串')
// 如果包含,则返回 true ,否则返回 false
if (item.name.includes(keywords)) {
return item
}
})
// return newList
}
概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;
私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用
HTML
<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>
Vue实例
filters: {
// 第一个参数接收过滤器前面的值,后面的参数接收过滤器的参数
dataFormat(input, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错
var dt = new Date(input);
// 获取年月日
var y = dt.getFullYear();
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
// month从0开始,所以要+1
var d = dt.getDate().toString().padStart(2, '0');
// padStart(2, '0')把个位数转化为01,02的两位数
// 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日
// 否则,就返回 年-月-日 时:分:秒
if (pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`;
} else {
// 获取时分秒
var hh = dt.getHours().toString().padStart(2, '0');
var mm = dt.getMinutes().toString().padStart(2, '0');
var ss = dt.getSeconds().toString().padStart(2, '0');
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}
}
}
使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString=’’) 或 String.prototype.padEnd(maxLength, fillString=’’)来填充字符串;
HTML
<div id="app">
<p>{{ msg | msgFormat('疯狂', '123') | test }}</p>
</div>
vue实例
// 定义一个 Vue 全局的过滤器,名字叫做 msgFormat
Vue.filter('msgFormat', function (msg, arg, arg2) {
// 字符串的 replace 方法,第一个参数,除了可写一个 字符串之外,还可以定义一个正则
return msg.replace(/内容/g, arg + arg2)
})
Vue.filter('test', function (msg) {
return msg + '========'
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '一段内容'
},
methods: {}
});
注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!
Vue.config.keyCodes.名称 = 按键值
来自定义案件修饰符的别名:Vue.config.keyCodes.f2 = 113;
<input type="text" v-model="name" @keyup.f2="add">
注意: 在每个函数中,第一个参数永远是 el ,它表示被绑定了指令的那个元素。这个 el 参数,是一个原生的JS对象
// 自定义全局指令 v-focus,为绑定的元素自动获取焦点:
Vue.directive('focus', {
inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用
el.focus();
}
});
// 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细:
directives: {
color: { // 为元素设置指定的字体颜色
bind(el, binding) {
el.style.color = binding.value;
}
},
'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数
el.style.fontWeight = binding2.value;
}
}
<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900">
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次 inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】。 update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
:一个对象,包含以下属性: 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
钩子中可用。computed
属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;必须returnmethods
方法表示一个具体的操作,主要书写业务逻辑;watch
属性的值是一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computed
和methods
的结合体;通过一个demo,来介绍三者的区别和使用方法。
实现姓、名两个文本框的内容的改变,则全名的文本框中的值也跟着改变
通过监听keyup事件,然后调用方法实现
<div id="app">
<input type="text" v-model="firstname" @keyup="getFullname"> +
<input type="text" v-model="lastname" @keyup="getFullname"> =
<input type="text" v-model="fullname">
</div>
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
methods: {
getFullname() {
this.fullname = this.firstname + '-' + this.lastname
}
}
});
<div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<input type="text" v-model="fullname">
</div>
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
methods: {},
watch: { // 使用watch属性可以监视 data 中指定数据的变化,然后触发 watch 中对应的 function 处理函数
'firstname': function (newVal, oldVal) {
// newVal, oldVal分别是变化前的值和变化后的值
this.fullname = newVal + '-' + this.lastname
},
'lastname': function (newVal) {
this.fullname = this.firstname + '-' + newVal
}
}
});
getter
的计算属性<div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<input type="text" v-model="fullname">
</div>
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: ''
},
methods: {},
computed: { // 在 computed 中可以定义一些叫做 【计算属性】的属性,计算属性的本质就是一个方法,只不过在使用这些计算属性时,是把它们的名称直接当作属性来使用的;并不会把计算属性当作方法去调用;
// 注意1:在引用计算属性时,不要加()去调用,直接把它当作普通属性去使用;
// 注意2:只要计算属性的 function 内部,所用到的任何 data 中的数据发送了变化,就会立即重新计算这个计算属性的值
// 注意3:计算属性的结果会被缓存起来,方便下次直接使用;如果计算属性方法中的任何数据都没有发生过变化,则不会重新对计算属性求值;即不会重新执行这个方法
'fullname': function () {
console.log('ok')
return this.firstname + '-' + this.lastname
}
}
});
getter
和setter
的计算属性<div id="app">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<!-- 点击按钮重新为 计算属性 fullName 赋值 -->
<input type="button" value="修改fullName" @click="changeName">
<span>{{fullName}}</span>
</div>
var vm = new Vue({
el: '#app',
data: {
firstName: 'jack',
lastName: 'chen'
},
methods: {
changeName() {
this.fullName = 'TOM - chen2';
}
},
computed: {
fullName: {
get: function () {
return this.firstName + ' - ' + this.lastName;
},
set: function (newVal) {
var parts = newVal.split(' - ');
this.firstName = parts[0];
this.lastName = parts[1];
}
}
}
});
作用:提供了一些最常用的NPM包镜像地址,能够让我们快速的切换安装包时候的服务器地址; 什么是镜像:原来包刚一开始是只存在于国外的NPM服务器,但是由于网络原因,经常访问不到,这时候,我们可以在国内,创建一个和官网完全一样的NPM服务器,只不过,数据都是从人家那里拿过来的,除此之外,使用方式完全一样;
npm i nrm -g
全局安装nrm
包;nrm ls
查看当前所有可用的镜像源地址以及当前所使用的镜像源地址;nrm use npm
或nrm use taobao
切换不同的镜像源地址;