vue基础知识
vue教程
vue官网
BootCDN
我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 <script> 标签引入。
或者从CDN上面搜索vue,复制地址引入
每个 Vue 应用都需要通过实例化 Vue 来实现。
语法格式如下:
var vm = new Vue({
// 选项...
})
var vue = new Vue({
//绑定
el: '#app',
//实例内自定义局部组件
components: {
'runoob': Child
},
//也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用
directives: {
// 注册一个局部的自定义指令 v-focus
focus: {
// 指令的定义
inserted: function (el) {
// 聚焦元素
el.focus()
}
}
},
//数据
data: {
msg: 'hello shadow,hello vue!',
count: 15,
message: '<h2>明天你好</h2>',
use: false,
url: "http://www.baidu.com",
filtersData: "hello",
list1: [1, 2, 3, 4, 5],
list2: [{ name: 'shadow', age: 18 }, { name: 'tom', age: 88 }],
object: {
name: 'shadow',
url: 'http://www.baidu.com',
slogan: '吃好喝好玩好!'
},
isActive: true,
hasError: true,
error: {
value: true,
type: 'fatal'
},
message3: '',
message2: '',
sites: [
{ text: 'Runoob' },
{ text: 'Google' },
{ text: 'Taobao' }
],
total: 0
},
//方法
methods: {
details() {
return "hello world!!!"
},
addCount() {
this.count++;
},
say(meassage) {
alert(meassage)
},
incrementTotal: function () {
this.total += 1
}
},
//筛选
filters: {
//取第一个字符,转换大写
capitalize(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
},
//监听,只能监听一个数据变量的变化 通过 watch 来响应数据的变化。
watch: {
//监听变量msg的变化
msg(newVlue, oldValue) {
console.log("old:" + oldValue + "---new:" + newVlue)
}
},
//计算,可以动态监听构成msg1的所有数据的变化,任意一个变量变化,msg1就会发生变化
//计算属性在处理一些复杂逻辑时是很有用的
//可以使用 methods 来替代 computed,效果上两个都是一样的,
//但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
//而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
//如果你不希望缓存,你可以使用 methods 属性
computed: {
msg1() {
return this.msg + "---" + this.count
},
classObject: function () {
return {
base: true,
active: this.isActive && !this.error.value,
'text-danger': false,
}
}
}
});
可以看到在 Vue 构造器中有一个el 参数,它是 DOM 元素中的 id。 这意味着我们接下来的改动全部在以上指定的 div 内,div 外部不受影响
data 用于定义属性
methods 用于定义的函数,可以通过 return 来返回函数值。
{{ }} 用于输出对象属性和函数返回值
当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。
当这些属性的值发生改变时,html 视图将也会产生相应的变化。
除了数据属性,Vue 实例还提供了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来
vue.$watch('count', function (nval, oval) {
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
======插值=======
数据绑定最常见的形式就是使用 {{...}}(双大括号)的文本插值
======属性=========
HTML 属性中的值应使用 v-bind 指令。
Vue.js 都提供了完全的 JavaScript 表达式支持。
========指令============
指令是带有 v- 前缀的特殊属性。
使用 v-html 指令用于输出 html 代码:
指令用于在表达式的值改变时,将某些行为应用到 DOM 上
v-if 指令
将根据表达式 seen 的值(true 或 false )来决定是否插入 p 元素。
可以用 v-else 指令给 v-if 添加一个 "else" 块:
v-else-if 在 2.1.0 新增,顾名思义,用作 v-if 的 else-if 块。可以链式的多次使用
也可以使用 v-show 指令来根据条件展示元素:
<div id="app">
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
type: 'C'
}
})
</script>
v-bind 指令被用来响应地更新 HTML 属性
class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性。
Vue.js v-bind 在处理 class 和 style 时, 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组
可以为 v-bind:class 设置一个对象,从而动态的切换 class:
<div v-bind:class="{ active: isActive }"></div>
也可以在对象中传入更多属性用来动态切换多个 class 。
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
也可以直接绑定数据里的一个对象:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class="classObject"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
classObject: {
active: true,
'text-danger': true
}
}
})
</script>
</body>
也可以在这里绑定返回对象的计算属性
可以把一个数组传给 v-bind:class
<div v-bind:class="[activeClass, errorClass]"></div>
还可以使用三元表达式来切换列表中的 class :
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
可以在 v-bind:style 直接设置样式:
<div id="app">
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div>
</div>
也可以直接绑定到一个样式对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<div v-bind:style="styleObject">菜鸟教程</div>
</div>
<script>
new Vue({
el: '#app',
data: {
styleObject: {
color: 'green',
fontSize: '30px'
}
}
})
</script>
</body>
</html>
v-bind:style 可以使用数组将多个样式对象应用到一个元素上:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<div v-bind:style="[baseStyles, overridingStyles]">菜鸟教程</div>
</div>
<script>
new Vue({
el: '#app',
data: {
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
})
</script>
</body>
</html>
v-bind 缩写
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
v-on 指令,它用于监听 DOM 事件 <a v-on:click="doSomething">
v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
v-model 指令来实现双向数据绑定:
v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
vue.js 允许你自定义过滤器,被用作一些常见的文本格式化
<!-- 在两个大括号中 -->
{{ message | capitalize }}
<!-- 在 v-bind 指令中 -->
<div v-bind:id="rawId | formatId"></div>
过滤器函数接受表达式的值作为第一个参数。
<div id="app">
{{ message | capitalize }}
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'runoob'
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
</script>
循环使用 v-for 指令。
v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。
v-for 可以绑定数据到数组来渲染一个列表
v-for 可以通过一个对象的属性来迭代数据:
<div id="app">
<ol>
<li v-for="site in sites">
{{ site.name }}
</li>
</ol>
</div>
<script>
new Vue({
el: '#app',
data: {
sites: [
{ name: 'Runoob' },
{ name: 'Google' },
{ name: 'Taobao' }
]
}
})
</script>
你也可以提供第二个的参数为键名:
<div id="app">
<ul>
<li v-for="(value, key) in object">
{{ key }} : {{ value }}
</li>
</ul>
</div>
第三个参数为索引:
<div id="app">
<ul>
<li v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</li>
</ul>
</div>
v-for 迭代整数
<div id="app">
<ul>
<li v-for="n in 10">
{{ n }}
</li>
</ul>
</div>
计算属性关键词: computed。
计算属性在处理一些复杂逻辑时是很有用的
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Runoob!'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
</script>
Vue.js 监听属性 watch,我们可以通过 watch 来响应数据的变化
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id = "computed_props">
千米 : <input type = "text" v-model = "kilometers">
米 : <input type = "text" v-model = "meters">
</div>
<p id="info"></p>
<script type = "text/javascript">
var vm = new Vue({
el: '#computed_props',
data: {
kilometers : 0,
meters:0
},
methods: {
},
computed :{
},
watch : {
kilometers:function(val) {
this.kilometers = val;
this.meters = this.kilometers * 1000
},
meters : function (val) {
this.kilometers = val/ 1000;
this.meters = val;
}
}
});
// $watch 是一个实例方法
vm.$watch('kilometers', function (newValue, oldValue) {
// 这个回调将在 vm.kilometers 改变后调用
document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
})
</script>
</body>
</html>
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
<tagName></tagName>
全局组件 可以在全局使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<runoob></runoob>
</div>
<script>
// 注册
Vue.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
</body>
</html>
局部组件 只能在当前vue实例中使用
<div id="app">
<runoob></runoob>
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
components: {
// <runoob> 将只在父模板可用
'runoob': Child
}
})
</script>
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<child message="hello!"></child>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
</body>
</html>
动态 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>
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<style>
.class1 {
background: #444;
color: #eee;
}
.class2 {
color: red;
}
.active {
width: 100px;
height: 100px;
background: green;
}
.text-danger {
background: red;
}
</style>
<body>
<div id="app">
<h1>{{msg}}</h1>
<h1>{{count + 1}}</h1>
<!-- 调用方法 -->
<h1>{{details()}}</h1>
<div>
<label for="r1">修改颜色</label>
<!-- v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。 -->
<!-- v-model 指令在表单控件元素上创建双向数据绑定。 -->
<input type="checkbox" v-model="use" id="r1">
<br><br>
<!-- v-bind 动态指定class -->
<div v-html="message" v-bind:class="{'class1':use}"></div>
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
<!-- 绑定计算属性 -->
<div v-bind:class="classObject"></div>
</div>
<p>输入框 input 元素:</p>
<input v-model="message3" placeholder="编辑我……">
<p>消息是: {{ message3 }}</p>
<p>textarea 元素:</p>
<textarea v-model="message2" placeholder="多行文本输入……"></textarea>
<p style="white-space: pre">{{ message2 }}</p>
<!-- 数据计算 -->
<h1>{{message.split('').reverse().join('')}}</h1>
<h1>{{use ?"hello shadow":"hello tomorrow"}}</h1>
<h1 v-if="use">你能不能看到我啊</h1>
<!-- v-bind -->
<pre><a v-bind:href="url">动态绑定URL</a></pre>
<!-- v-on -->
<button v-on:click="addCount">动态加数</button>
<button @click='say("hi")'>Say hi</button>
<!-- 筛选 -->
<h1>{{filtersData |capitalize }}</h1>
<!-- 计算 -->
<h1>{{msg1}}</h1>
<!-- v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。-->
<div v-for="item in list1">
<span :class="{'class2':item > 2 && item < 5}">{{item}}</span>
</div>
<!-- v-for 可以通过一个对象的属性来迭代数据: -->
<div class="class2" v-for="value in object">{{value}}</div>
<!-- v-for 可以通过一个对象的属性来迭代数据: -->
<div class="class1" v-for="(value,key) in object">{{key}}:{{value}}</div>
<!-- v-for 遍历对象 -->
<span v-for='item in list2'>
{{item.name}}
</span>
<!-- v-for 迭代整数 -->
<div>
<ul>
<li v-for='n in 10'>
{{n}}
</li>
</ul>
</div>
<!-- v-if -->
<div>
<h4 v-if="count > 10">判断1 count > 10 : {{count}}</h4>
<h4 v-else-if="count == 5">判断2 count == 5 {{count}}</h4>
<h4 v-else>判断3 {{count}}</h4>
<h4 v-show='count == 5'>hello v-show</h4>
</div>
<!-- 自定义组件 -->
<!-- 也可以用 v-bind 动态绑定 props 的值到父组件的数据中。
每当父组件的数据变化时,该变化也会传导给子组件 -->
<!-- prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 -->
<shadow-text v-bind:message="msg"></shadow-text>
<shadow-text message="传递参数"></shadow-text>
<runoob></runoob>
<!-- 传递数组数据 -->
<ol>
<todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
</ol>
<!-- 自定义组件 自定义事件 -->
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
<!-- 自定义指令 -->
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-focus>
</div>
<script>
//除了数据属性,Vue 实例还提供了一些有用的实例属性与方法。
//它们都有前缀 $,以便与用户定义的属性区分开来。
var data = {
msg: 'hello shadow,hello vue!',
count: 15,
message: '<h2>明天你好</h2>',
use: false,
url: "http://www.baidu.com",
filtersData: "hello",
list1: [1, 2, 3, 4, 5],
list2: [{ name: 'shadow', age: 18 }, { name: 'tom', age: 88 }],
object: {
name: 'shadow',
url: 'http://www.baidu.com',
slogan: '吃好喝好玩好!'
},
isActive: true,
hasError: true,
error: {
value: true,
type: 'fatal'
},
message3: '',
message2: '',
sites: [
{ text: 'Runoob' },
{ text: 'Google' },
{ text: 'Taobao' }
],
total: 0
}
// 所有实例都能用全局组件。 tagName 为组件名,options 为配置选项
//prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
//父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
Vue.component('shadow-text', {
// 声明 props
props: ['message'],
template: "<h1>vue 自定义组件 {{message}}</h1>"
})
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
// 自定义事件
//父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
//我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
//使用 $on(eventName) 监听事件
//使用 $emit(eventName) 触发事件
//另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
//以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
}
},
})
var Child = {
template: '<h1> 实例内 局部自定义组件!</h1>'
}
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
var vue = new Vue({
//绑定
el: '#app',
//实例内自定义局部组件
components: {
'runoob': Child
},
//也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用
// directives: {
// // 注册一个局部的自定义指令 v-focus
// focus: {
// // 指令的定义
// inserted: function (el) {
// // 聚焦元素
// el.focus()
// }
// }
// },
//数据
data: data,
//方法
methods: {
details() {
return "hello world!!!"
},
addCount() {
this.count++;
},
say(meassage) {
alert(meassage)
},
incrementTotal: function () {
this.total += 1
}
},
//筛选
filters: {
//取第一个字符,转换大写
capitalize(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
},
//监听,只能监听一个数据变量的变化 通过 watch 来响应数据的变化。
watch: {
//监听变量msg的变化
msg(newVlue, oldValue) {
console.log("old:" + oldValue + "---new:" + newVlue)
}
},
//计算,可以动态监听构成msg1的所有数据的变化,任意一个变量变化,msg1就会发生变化
//计算属性在处理一些复杂逻辑时是很有用的
//可以使用 methods 来替代 computed,效果上两个都是一样的,
//但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
//而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
//如果你不希望缓存,你可以使用 methods 属性
computed: {
msg1() {
return this.msg + "---" + this.count
},
classObject: function () {
return {
base: true,
active: this.isActive && !this.error.value,
'text-danger': false,
}
}
}
});
vue.$watch('count', function (nval, oval) {
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
document.write(vm.$data === data) // true
document.write("<br>")
</script>
</body>
</html>