new Vue
el
查找标签的参数data
存放数据的参数methods
封装函数的参数<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
{{ message }}
div>
body>
<script src="js/vue.js">script>
<script>
// 这是我们的Model
var exampleData = {
message: 'Hello World!'
}
// 创建一个 Vue 实例或 "ViewModel"
// 它连接 View 与 Model
new Vue({
el: '#app',
data: exampleData
})
script>
html>
ViewModel
,它用于连接View和Model在创建Vue实例时,需要传入一个选项对象,选项对象可以包含数据
、挂载元素
、方法
、模生命周期钩子
等等。
View
,el: '#app'
表示该Vue实例将挂载到...
这个元素;data属性指向Model
,data: exampleData
表示我们的Model是exampleData对象 文本插值(也叫大胡子)
,使用一对大括号语法,在运行时{{ message }}
会被数据对象
的message属性
替换,所以页面上会输出”Hello World!”。 MVVM模式本身是实现了双向绑定的,在Vue.js中可以使用v-model
指令在表单元素上创建双向数据绑定。
<div id="app">
<p>{{ message }}p>
<input type="text" v-model="message"/>
div>
可以把上面的代码,给它包含在< body>标签中进行一下运行,能更深刻的理解一下v-model
指令的双向绑定。
v-开头的
,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性 v-if
是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下:
v-if="content"
v-if取值为false不是隐藏 是删除标签(销毁标签)
<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
<h1>Hello, Vue.js!h1>
<h1 v-if="yes">Yes!h1>
<h1 v-if="no">No!h1>
<h1 v-if="age >= 25">Age: {{ age }}h1>
<h1 v-if="name.indexOf('fe') >= 0">Name: {{ name }}h1>
div>
body>
<script src="vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'fe_cow'
}
})
script>
html>
大家能想象出来下面的页面哪些数据不会出现么 ?
yes
属性为true,所以“YES!”会被输出。no
属性为false,所以”No!”不会被输出。age >= 25
返回true,所以”Age: 28”会被输出。name.indexOf('fe') >= 0
返回false,所以”Name: fe_cow”会被输出。v-if指令是根据条件表达式的值(v-if='xxx')来执行元素的插入或者删除行为。
可以用v-else
指令为v-if
或v-show
添加一个“else块”。v-else
元素必须立即跟在v-if
或v-show
元素的后面——否则它不能被识别。
<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
<h1 v-if="age >= 25">Age: {{ age }}h1>
<h1 v-else>Name: {{ name }}h1>
<h1>---------------------分割线---------------------h1>
<h1 v-show="name.indexOf('1') >= 0">Name: {{ name }}h1>
<h1 v-else>Sex: {{ sex }}h1>
div>
body>
<script src="vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
age: 28,
name: 'fe_cow',
sex: 'cow'
}
})
script>
html>
v-else
元素是否渲染在HTML中,取决于前面使用的是v-if
还是v-show
指令。
v-if
为true,后面的v-else
不会渲染到HTML;v-show
为true,但是后面的v-else
仍然可以渲染到HTML中。
v-show
也是条件渲染指令,和v-if指令不同的是,使用v-show
指令的元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性。
下面我们举个栗子:
<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
<h1>Hello, Vue.js!h1>
<h1 v-show="yes">Yes!h1>
<h1 v-show="no">No!h1>
<h1 v-show="age >= 25">Age: {{ age }}h1>
<h1 v-show="name.indexOf('fe') >= 0">Name: {{ name }}h1>
div>
body>
<script src="vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'fe_cow'
}
})
script>
html>
可能有同学会发现,这不是更上面的v-if
没有什么区别么?指示命令换成了v-show
No!
,发现跟上面的v-if
的区别了吧。提高代码执行效率
可以用v-show
,但是如果是多个标签
之前切换显示隐藏只能用v-if。v-for
指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="i in mylist"> {{ i }}li>
ul>
<ul>
<li v-for="(i, j) in mylist">{{j+1}}、{{ i }}li>
ul>
<ul>
<li v-for="i in mydict">{{ i }}li>
ul>
<ul>
<li v-for="(i, j) in mydict">{{ j }}:{{i}}li>
ul>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
mylist: ['邪不压正1', '邪不压正2', '邪不压正3'],
mydict: {'name':'laowang', 'age':38}
}
})
script>
body>
html>
data属性
中定义了一个mylist数组
,mydicct字典
,然后在#app元素
内使用v-for
遍历mylist数组和mydict字典。数组可以输出索引
,字典也可以输出键值
,这点跟python中拆包
很像。控制html内容
和控制html属性
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{ num }}div>
<div>{{ str }}div>
<div>{{ num + 1}}div>
<div>{{ str.split('').reverse().join('') }}div>
<div>{{ bool?'成立':'不成立' }}div>
<a v-bind:href="url1" class="box">控制html属性hrefa>
<a :href="url2">控制html属性href 淘宝a>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
num:1,
str:'abcdefg',
bool:false,
url1:'http://www.baidu.com',
url2:'http://www.taobao.com'
}
})
script>
body>
html>
isclass1
是true的话,就会绑定class1
这个类。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div :class="{class1:isclass1, class2:isclass2}">1111111111111div>
<div :class="myobject1">222222222div>
<div :class="[myclass3, myclass4]">333333div>
<div :class="[isclass2?'aa':'bb']">44444444div>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
isclass1:true,
isclass2:false,
myobject1:{
active:false,
current:true
},
myclass3:'class3',
myclass4:'class4'
}
})
script>
body>
html>
v-on
指令用于给监听DOM事件,它的用语法和v-bind是类似的,例如监听< a>元素的点击事件:
有两种形式调用方法:绑定一个方法(让事件指向方法的引用),或者使用内联语句。
<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
<p><input type="text" v-model="message">p>
<p>
<button v-on:click="greet">Greetbutton>
p>
<p>
<button v-on:click="say('Hi')">Hibutton>
p>
div>
body>
<script src="js/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js!'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function() {
// // 方法内 `this` 指向 vm
alert(this.message)
},
say: function(msg) {
alert(msg)
}
}
})
script>
html>
Vue.js为最常用的两个指令v-bind
和v-on
提供了缩写方式。v-bind指令可以缩写为一个冒号
,v-on指令可以缩写为@符号
。
<a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}a>
<a href="javascripit:void(0)" :class="activeNumber=== n + 1 ? 'active' : ''">{{ n + 1 }}a>
<button v-on:click="greet">Greetbutton>
<button @click="greet">Greetbutton>
每个表单的name
代表的是key,value
代表输入的值。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="txt">
<div>{{ txt }}div>
<select v-model="sel">
<option value="0">北京option>
<option value="1">上海option>
<option value="2">广州option>
select>
<div>{{sel}}div>
<input type="radio" value="nan" v-model="rad">男 <input type="radio" value="nv" v-model="rad">女
<div>{{ rad }}div>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
txt:'请输入用户名',
sel:0,
rad:'nv'
}
})
script>
body>
html>
第一种方式 Vue中的class对象
绑定:
!this.xxxx :取反的意思
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中class对象绑定title>
<script src="js/vue.js">script>
<style>
.activated{
color: red;
}
style>
head>
<body>
<div id="app">
<div @click="handleDivClick"
:class="{activated: isActivated}">
hello world
div>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
isActivated: false
},
//!this.isActivated 取反的意思
methods: {
handleDivClick: function () {
this.isActivated = !this.isActivated
}
}
})
script>
body>
html>
数组
:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中class数组绑定title>
<script src="js/vue.js">script>
<style>
.activated{
color: red;
}
style>
head>
<body>
<div id="app">
<div @click="handleDivClick"
:class="[activated, activatedOne]">
hello world
div>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
activated: '',
activatedOne: 'activated-one'
},
// 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
methods: {
handleDivClick: function () {
this.activated = this.activated === 'activated'? '':'activated'
}
}
})
script>
body>
html>
第三种方式:通过style对象和数组来表达:
还可以在style数组中给它添加一个样式: :style="[styleObj, {fontSize:'20px'}]"
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中style 对象和数组绑定title>
<script src="js/vue.js">script>
<style>
.activated{
color: red;
}
style>
head>
<body>
<div id="app">
<div @click="handleDivClick"
:style="[styleObj, {fontSize:'20px'}]">
hello world
div>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj: {
color: 'black'
}
},
// 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
methods: {
handleDivClick: function () {
this.styleObj.color = this.styleObj.color === 'black'? 'red':'black'
}
}
})
script>
body>
html>
每次循环的时候,循环标签中最好都带有:key='item.id'
值,会提高性能。
当想要修改数组的内容的时候,不能通过修改下边的vm.list[0] = {id:'111',text:'222'}
执行,应该采用·数组的变异方法:(push,pop,shift,unshift,splice,sort,reverse)
引用
:vm.list = [{},{},{}]
Vue.set(vm.对象名, 1下标, 5更改的名字)
vm.$set(vm.对象名, 1下标, 5更改的名字)
template:模板占位符
给对象添加数据:
Vue.set
(vm.对象名, “address”,”beijing’) 就可以了
通过Vue实例方法实现:`vm.$set(vm.对象名, ”address’,’beijing’)
生命周期钩子
的函数,我们可以使用这些函数,在实例的不同阶段加上我们需要的代码,实现特定的功能。 实例初始化之后
,数据观测 (data observer)
和event/watcher 事件配置之前
被调用。 实例创建完成
后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调
。然而,挂载阶段还没开始。挂载开始之前
被调用:相关的 render 函数首次
被调用。 实例挂载到dom之后
被调用,可以当成是vue对象的ready方法
来使用,一般用它来做dom的初始化操作
。 组件被销毁之前
调用。组件销毁之后调用
。数据发生变化前
调用。数据发生变化后
调用 。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VUE实例生命周期函数title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
div>
<script>
// 生命周期函数就是vue实例在某一个时间点会自动执行的函数
var vm = new Vue({
el:'#app',
template:"{{test}}",
data: {
test:'hello word'
},
// 在实例初始化之后调用
beforeCreate: function () {
console.log("beforCreate")
},
//在实例创建完成后立即调用
created: function () {
console.log("created")
},
// 在挂载开始之前被调用 在有template模板的时候不渲染
beforeMount: function(){
console.log(this.$el)
console.log("beforeMount")
},
// 在挂载之后可以调用 在实例中有tempalte模板的时候渲染里面的内容
mounted: function () {
console.log(this.$el)
console.log("mounted")
},
// 在组件被销毁之前它会被执行 在控制台打vm.$destroy()就会执行这俩个方法
beforeDestroy: function () {
console.log("beforeDestroy")
},
// 在组件被销毁之后它会执行
destroyed:function () {
console.log("destroyed")
},
// 在数据被改变之前会执行 在控制台输入: vm.test="dell" beforeUpdate 和 updated就会被调用
beforeUpdate: function () {
console.log("beforeUpdate")
},
// 在数据被改变之后会执行
updated:function () {
console.log("updated")
}
})
script>
body>
html>
第一种:插值表达式{{}}
第二种:在 < div v-text=’name’> < /div>
第三种:在< div v-html=’name’> < /div>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{name + 'fe_cow'}}div>
<div v-text="name + 'fe_cow'">div>
<div v-html="name + 'fe_cow'">div>
div>
<script>
var vm = new Vue({
el:'#app',
data: {
name:'fe_cow'
// name:'fe_cow
'
}
})
script>
body>
html>
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。计算属性还有缓存
机制, 计算属性有返回值
。例如:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性 computed方法 缓存机制title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{fullName}}div>
<div>{{age}}div>
div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
// 计算属性的缓存, 在控制台中打vm.age = 28 可以观察看,并没有走fullName这里,因为fullName中的this.firstName 和 lastName都没有发生改变
computed: {
fullName: function () {
console.log('执行了一次计算')
return this.firstName + this.lastName
}
}
})
script>
body>
html>
使用methods
方法 差值表达式后面有()
也能达到计算属性,但是建议不使用,因为它没有缓存:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性 methods 不建议使用 没有缓存机制title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{fullName()}}div>
<div>{{age}}div>
div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
methods: {
fullName: function () {
console.log('执行了一次计算')
return this.firstName + this.lastName
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性的setter 和 gettertitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{fullName}}div>
<div>{{age}}div>
div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
computed: {
// 在控制台打 vm.fullName = 'hello word' 改变了fullName的值,set中的value就会接收到 进行切割,重新给firstName 和 lastName重新赋值
fullName:{
get: function () {
return this.firstName + this.lastName
},
// value set接收到get中 fullName中的值
set: function (value) {
console.log('进入了Set里面')
var arr = value.split(' ')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
script>
body>
html>
侦听属性的作用是侦听某属性值的变化
,从而做相应的操作,侦听属性是一个对象
,它的键
是要监听的对象
或者变量
,值一般是函数
,当你侦听的元素发生变化时,需要执行的函数,这个函数有两个形参,第一个是当前值
,第二个是变化后的值
。
data
中的fullName
,如果firstName发生改变,就会调用watch方法,就会改变fullName的值。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监听属性 watchtitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{fullName}}div>
<div>{{age}}div>
div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
fullName: 'Fe_cow',
age: 27
},
watch: {
firstName:function(){
console.log('执行一次')
this.fullName = this.firstName + this.lastName
},
lastName: function () {
console.log('执行二次')
this.fullName = this.firstName + this.lastName
}
}
})
script>
body>
html>
Vue.js允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值
和 v-bind 表达式
。
{{ prize | RMB }}
<div v-bind:id="rawId | formatId">div>
过滤器实际上是一个函数,可以在一个组件的选项中定义组件内部过滤器:
filters:定义的是局部变量
:需要在实例内部定义
:
filters:{
RMB:function(value){
if(value=='')
{
return;
}
return '¥ '+value;
}
}
或者在创建 Vue 实例之前全局定义过滤器
:
Vue.filter('名字',匿名函数){}:定义全局变量:
Vue.filter('Yuan',function(value){
if(value=='')
{
return;
}
return value+'元';
});
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<div>{{ price1 | yuan | RMB}}div>
<div>{{ price2 | yuan | RMB}}div>
div>
<div id="box">
<div>{{ price1 | RMB }}div>
<div>{{ price2 |RMB }}div>
div>
<script>
// 全局过滤器:作用于所有对象 -- 要求全局过滤器必须定义再所有对象的上面
// Vue.filter(名字,function(){})
Vue.filter('RMB', function(vals){
if(vals == 0){
return vals
}
return '¥' + vals
})
var box = new Vue({
el:'#box',
data:{
price1:999,
price2:0
}
})
var vm = new Vue({
el:'#app',
data:{
price1:99,
price2:0
},
filters:{
// mingzi:function(){}
yuan:function(vals){
if(vals == 0)
{
return vals
}
return vals +'元'
}
}
})
script>
body>
html>
组件(Component)是Vue.js最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
基本步骤:
Vue.js的组建的使用有3个步骤:1.创建组件构造器 2.注册组件 3.使用组件。
调用Vue.extend()方法
创建组件构造器。
Vue.compoent()方法
注册组件。Vue实例
的作用范围内使用组件。
<html>
<body>
<div id="app">
<my-component>my-component>
div>
body>
<script src="js/vue.js">script>
<script>
// 1.创建一个组件构造器 模板是div标签组成的
var myComponent = Vue.extend({
template: 'This is my first component!'
})
// 2.注册组件,并指定组件的标签,组件的HTML标签为
Vue.component('my-component', myComponent)
new Vue({
el: '#app'
});
script>
html>
接下来我们用以下几个步骤来理解组件的创建和注册:
vue.extend()
是Vue构造器的扩展,调用vue.extend
创建一个组件构造器。vue.extend()
构造器有一个选项对象,选项对象的template
属性用于定义组件要渲染的HTML。 Vue.component()
注册组件时,需要提供2个参数,第1个参数是组件的标签,第2个参数是组件构造器。
<html>
<body>
<div id="app1">
<my-component>my-component>
div>
<div id="app2">
<my-component>my-component>
div>
<my-component>my-component>
body>
<script src="js/vue.js">script>
<script>
var myComponent = Vue.extend({
template: 'This is a component!'
})
Vue.component('my-component', myComponent)
var app1 = new Vue({
el: '#app1'
});
var app2 = new Vue({
el: '#app2'
})
script>
html>
在子组件中绑定原生事件:@click.native="handleClick"
<html lang="en">
<head>
<meta charset="UTF-8">
<title>给组件绑定原生事件title>
<script src="js/vue.js">script>
head>
<body>
<div id="root">
<child @click.native="handleClick">child>
div>
<script>
Vue.component('child',{
template: 'Childdiv>'
})
var vm = new Vue({
el:'#root',
methods:{
handleClick:function () {
alert('handleClick')
}
}
})
script>
body>
html>
.bus
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非父子组件间传值(Bus/总线/发布订阅者模式/观察者模式)title>
<script src="js/vue.js">script>
head>
<body>
<div id="root">
<child content="Fe">child>
<child content="cow">child>
div>
<script>
Vue.prototype.bus = new Vue()
Vue.component('child',{
// 进行赋值
data: function() {
return {
selfCountent: this.content
}
},
// 把父组件传递过来的参数 进行校验
props: {
content: String
},
template: '{{selfCountent}}div>',
// 点击子组件触发的事件
methods:{
handleClick: function () {
this.bus.$emit('change', this.selfCountent)
}
},
mounted: function () {
var this_ = this
this.bus.$on('change', function (msg) {
this_.selfCountent = msg
})
}
})
var vm = new Vue({
el:'#root'
})
script>
body>
html>
子组件中,引入新的标签,可以在标签中引入slot='head'
属性,然后在子组件的template:
给插槽占位。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的插槽title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<body-comtent>
<div class="head" slot="head">headdiv>
<div class="footer" slot="footer">footerdiv>
body-comtent>
div>
<script>
Vue.component('body-comtent', {
template:'' +
' ' +
'content' +
' ' +
''
})
var vm = new Vue({
el:'#app'
})
script>
body>
html>
应用场景:在子组件中需要使用循环时,父组件控制子组件:
:item=item
将数据传递给父组件。slot-scope="props"
它应该定义在tempalte
标签中。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的插槽作用域title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<body-comtent>
<template slot-scope="props">
<h1>{{props.item}}h1>
template>
body-comtent>
div>
<script>
Vue.component('body-comtent', {
data:function(){
return{
list: [1,2,3,4]
}
},
template:'
'
})
var vm = new Vue({
el:'#app'
})
script>
body>
html>
组件就是vue的实例,所有vue实例中属性和方法,组件中也可以用,但是data属性必须是一个函数,因为组件会重复使用在多个地方,为了使用在多个地方的组件数据相对独立,data属性需要用一个函数来返回值。
// 定义组件
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{{ counter }}button>',
data: function () {
return {
counter: 0
}
}
})
// 使用组件
<div id="example-2">
<simple-counter>simple-counter>
<simple-counter>simple-counter>
<simple-counter>simple-counter>
div>
......
new Vue({
el: '#example-2'
})
css: scoped
表示是接下来的css只针对这个组件生效。
记住单文组件写js,必须是模块导出的形式:export default{ }
。
@
符:就是src
文件夹。
调用vue.component()
注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。
如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components
属性实现局部注册。
<html>
<body>
<div id="app">
<my-component>my-component>
div>
body>
<script src="js/vue.js">script>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: 'This is my first component!'
})
new Vue({
el: '#app',
components: {
// 2. 将myComponent组件注册到Vue实例下
'my-component' : myComponent
}
});
script>
html>
我们可以在组件中定义并使用其他组件,这就构成了父子组件的关系。
<html>
<body>
<div id="app">
<parent-component>
parent-component>
div>
body>
<script src="js/vue.js">script>
<script>
var Child = Vue.extend({
template: 'This is a child component!
'
})
var Parent = Vue.extend({
// 在Parent组件内使用标签
template :'This is a Parent component
',
components: {
// 局部注册Child组件,该组件只能在Parent组件内使用
'child-component': Child
}
})
// 全局注册Parent组件
Vue.component('parent-component', Parent)
new Vue({
el: '#app'
})
script>
html>
分析一下代码:
var Child = Vue.extend(...)
定义一了个Child组件构造器。var Parent = Vue.extend(...)
定义一个Parent组件构造器。components: { 'child-component': Child }
,将Child组件注册到Parent组件,并将Child组件的标签设置为child-component
。template :'This is a Parent component
'
,在Parent组件内以标签的形式使用Child组件。Vue.component('parent-component', Parent)
全局注册Parent组件。Child组件是在Parent组件中注册的,它只能在Parent组件中使用,确切地说:子组件只能在父组件的template中使用。
举两个错误的栗子:
…
相当于运行时,它的一些子标签只会被当作普通的HTML来执行。<div id="app">
<parent-component>
parent-component>
<child-component>
child-component>
div>
以上组件注册的方式有些繁琐,Vue.js为了简化这个过程,提供了注册语法糖。
使用Vue.component()直接创建和注册组件:
// 全局注册,my-component1是标签名称
Vue.component('my-component1',{
template: 'This is the first component!'
})
var vm1 = new Vue({
el: '#app1'
})
Vue.component()
的第1个参数是标签名称
,第2个参数是一个选项对象
,使用选项对象的template属性定义组件模板。使用这种方式,Vue在背后会自动地调用Vue.extend()
。
在选项对象的components属性中实现局部注册:
var vm2 = new Vue({
el: '#app2',
components: {
// 局部注册,my-component2是标签名称
'my-component2': {
template: 'This is the second component!'
},
// 局部注册,my-component3是标签名称
'my-component3': {
template: 'This is the third component!'
}
}
})
< script>
标签
<html>
<body>
<div id="app">
<my-component>my-component>
div>
<script type="text/x-template" id="myComponent">
This is a component!div>
script>
body>
<script src="js/vue.js">script>
<script>
// 相当于给template模板定义了scrpt标签,通过id进行一个绑定
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
// template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译
script>
html>
使用< script>标签时,type指定为text/x-template
,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略< script>标签内定义的内容。
使用< template>
标签
如果使用
标签,则不需要指定type属性。
<html>
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div id="app">
<my-component>my-component>
div>
<template id="myComponent">
<div>This is a component!div>
template>
body>
<script src="js/vue.js">script>
<script>
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
script>
html>
在理解了组件的创建和注册过程后,我建议使用
组件的el和data选项
- 传入Vue构造器的多数选项也可以用在
Vue.extend()
或Vue.component()
中,不过有两个特例: data
和el
。
- Vue.js规定:在定义组件的选项时,
data
和el
选项必须使用函数。
使用Props
组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。
props基础示例:
下面的代码定义了一个子组件my-component,在Vue实例中定义了data选项。
var vm = new Vue({
el: '#app',
data: {
name: 'keepfool',
age: 28
},
components: {
'my-component': {
template: '#myComponent',
props: ['myName', 'myAge']
}
}
})
如果我们想使父组件的数据,则必须先在子组件中定义props属性,也就是props: ['myName', 'myAge']
这行代码。
定义子组件的HTML模板:
<template id="myComponent">
<table>
<tr>
<th colspan="2">
子组件数据
th>
tr>
<tr>
<td>my nametd>
<td>{{ myName }}td>
tr>
<tr>
<td>my agetd>
<td>{{ myAge }}td>
tr>
table>
template>
将父组件数据通过已定义好的props属性传递给子组件:
<div id="app">
<my-component v-bind:my-name="name" v-bind:my-age="age">my-component>
div>
在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。
在父组件中使用子组件时,通过一下语法将数据传递给子组件:
<child-component v-bind:子组件prop="父组件数据属性"></child-component>
prop的绑定类型
单向绑定
既然父组件将数据传递给了子组件,那么如果子组件修改了数据,对父组件是否会有所影响呢?
我们将子组件模板和页面HTML稍作更改:
<div id="app">
<table>
<tr>
<th colspan="3">父组件数据td>
tr>
<tr>
<td>nametd>
<td>{{ name }}td>
<td><input type="text" v-model="name" />td>
tr>
<tr>
<td>agetd>
<td>{{ age }}td>
<td><input type="text" v-model="age" />td>
tr>
table>
<my-component v-bind:my-name="name" v-bind:my-age="age">my-component>
div>
<template id="myComponent">
<table>
<tr>
<th colspan="3">子组件数据td>
tr>
<tr>
<td>my nametd>
<td>{{ myName }}td>
<td><input type="text" v-model="myName" />td>
tr>
<tr>
<td>my agetd>
<td>{{ myAge }}td>
<td><input type="text" v-model="myAge" />td>
tr>
table>
template>
修改了子组件的数据,没有影响父组件的数据。
修改了父组件的数据,同时影响了子组件。
prop默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态 。
双向绑定
可以使用.sync
显式地指定双向绑定,这使得子组件的数据修改会回传给父组件。
<my-component v-bind:my-name.sync="name" v-bind:my-age.sync="age"></my-component>
单次绑定
可以使用.once
显式地指定单次绑定,单次绑定在建立之后不会同步之后的变化,这意味着即使父组件修改了数据,也不会传导给子组件
<my-component v-bind:my-name.once="name" v-bind:my-age.once="age"></my-component>
数据交互:
- vue.js没有集成
ajax功能
,要使用ajax功能
,可以使用vue官方推荐的axios.js库来做ajax的交互
。
axios完整写法:
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
- axios请求的写法也写成
get方式
后post方式
。
执行get请求:
.then就是请求成功
、 .catch就是请求失败
- 有两种写法,可以用
params
来进行传参。
// 为给定 ID 的 user 创建请求
// then是请求成功时的响应,catch是请求失败时的响应
axios.get('/user?ID=12345')
// .then 就是请求成功
.then(function (response) {
console.log(response);
})
// .catch就是请求失败
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
执行post请求:
- 里面的参数就是key, value形式。
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
ES6语法
- ES6是JavaScript语言的新版本,它也可以叫做ES2015,之前学习的JavaScript属于ES5,ES6在它的基础上增加了一些语法,ES6是未来JavaScript的趋势,而且vue组件开发中会使用很多的ES6的语法,所以掌握这些常用的ES6语法是必须的 。
变量声明let和const
- let和const是新增的声明变量的开头的关键字,在这之前,变量声明是用var关键字,这两个关键字和var的区别是,它们声明的变量没有预解析,let和const的区别是,
let声明的是一般变量
,const申明的常量
,不可修改
。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script>
// alert(num1)
var num1 = 1
num1 = 10
// let const
// alert(num2)
let num2 = 2
num2 = 20
// alert(num3)
const num3 = 3 // 常量:不能修改值的变量
num3 = 30
script>
head>
<body>
body>
html>
箭头函数:
可以把箭头函数理解成匿名函数
的第二种写法,箭头函数的作用是可以在对象中绑定this
,解决了JavaScript中this指定混乱的问题。
var fn3(函数名) = (参数) => {命令}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script>
// function fn1(a, b){
// var rs = a + b
// alert(rs)
// }
// fn1(1, 2)
var fn2 = function(a, b){
var rs = a + b
alert(rs)
}
// fn2(1, 2)
// var fn3 = (参数) => {命令}
var fn3 = (a, b) => {
var rs = a + b
alert(rs)
}
// fn3(1, 2)
// 一个参数写法
var fn4 = a =>{
alert(a)
}
// fn4(1)
// 没有参数写法
var fn5 = () => {
alert('ok')
}
fn5()
script>
head>
<body>
body>
html>
对象的简写
javascript对象在ES6中可以做一些简写形式,了解这些简写形式,才能方便我们读懂一些在javascript代码中简写的对象。
下面的栗子:’laowang’的name和’laowang2’的name, key和value相等时,可以保留一个name
单词。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script>
// var laowang = {
// name:'laowang',
// age:38
// }
var name = 'laowang'
var age = 38
// var laowang2 = {
// name:name,
// age:38
// }
// es6如果遇到k和v的值相等,省略只保留一个单词也可以
var laowang2 = {
name,
age:38
}
alert(laowang2.name)
alert(laowang2.age)
script>
head>
<body>
body>
html>
模块导入import和导出export
javascript之前是没有模块的功能的,之前做js模块化开发,是用的一些js库来模拟实现的,在ES6中加入了模块的功能,和python语言一样,python中一个文件就是一个模块,ES6中,一个js文件就是一个模块
,不同的是,js文件中需要先导出(export)后
,才能被其他js文件导入(import)
。
// model.js文件中导出
var person = {name:'tom',age:18}
export default {person}
// index.js文件夹中导入
import person from 'js/model.js'
// index.js中使用模块
person.name
person.age
/*
上面导出时使用了default关键字,如果不使用这个关键字,导入时需要加大括号:
import {person} from 'js/model.js'
*/
页面结构说明:
- 1.index.html 首先加载的首页面
- 2.main.js 在加载main.js 文件
- 3.App.vue 路由
- 4.各个组件
- 总结就是:
- 整个项目是一个主文件
index.html
,index.html中会引入src文件夹
中的main.js
,main.js中会导入顶级单文件组件App.vue
,App.vue中会通过组件嵌套或者路由来引用components文件夹中
的其他单文件组件
。
组件嵌套:
将单文件组件组合在一起有两种方式,一种是嵌套方式,一种用路由的方式。嵌套的方式代码如下:
下图示中,假设组件A中要嵌入组件B。
`<template>
// 在A组件中使用B组件
<B_zujian>B_zujian>
template>
<script>
// 先导入B组件,其中'@'表示src目录,组件后的vue扩展名可以省略
import B_zujian from '@/components/B_zjian'
export default{
name:'A_zujian',
data:function(){
return {
iNum:0
}
},
// 接着在components属性选项中注册
components:{
B_zujian
}
}
script>`
路由:
- 可以通过路由的方式在一个组件中加载其他组件,要使用路由功能,需要在
main.js
中先导入路由的包
,然后在组件对象中还需要包含它。
import router from './router'
new Vue({
.....
router
})
组件中通过路由标签来加载其他的路由:
- 有简写的办法:
<router-view>router-view>
<router-view/>
路由标签里面加载哪个组件呢?在router文件中的index.js文件中设置:
import Vue from 'vue'
import Router from 'vue-router'
// 导入对应组件 '@' 表示src文件夹
import MainList from '@/components/MainList'
import UserList from '@/components/UserList'
import UpDate from '@/components/UpDate'
// 使用路由模块的固定写法
Vue.use(Router)
// path为'/'表示路由默认加载的组件
// 这些路由默认设置的是App.vue中的路由标签加载的组件
export default new Router({
routes: [
{
path: '/',
name: 'MainList',
component: MainList
},
{
path: '/user',
name: 'UserList',
component: UserList
},
{
path: '/update',
name: 'UpDate',
component: UpDate
}
]
})
通过链接可以切换路由标签里面对应的组件,链接的地址是上面index.js文件中定义的path值,不过链接标签是"router-link"
,链接地址用'to'来定义
:
<router-link to="/">内容router-link>
<router-link to="/user">内容router-link>
链接地址中可以传递参数,格式如下:
// name对应的是路由中定义的一个path对应的name属性
<router-link :to='{name:"UpDate",params:{code:item.code}}'>
有时候需要在组件的js中跳转页面,也就是改变路由,改变路由有下面这些方式:
// 当前页面重新加载
this.$router.go('/user');
// 跳转到另外一个路由
this.$router.push({path:'/user'});
// 获取当前的路由地址
var sPath = this.$route.path;
数据请求及跨域:
数据请求:
数据请求使用的是ajax,在vue中使用的axios.js
,这个文件可以在index.html文件中引入
,也可以作为模块导入,在main.js中导入这个模块
,然后将它绑定在Vue类的原型上:
import axios from 'axios'
Vue.prototype.axios = axios
重点:在组件的js代码中使用axios
:
this.axios({......})
跨域请求:
vue的自动化工具提供了开发的服务器,我们在这个服务器环境下开发,改动代码可以马上更新显示,错误了还有代码提示,非常方便,但是,如果我们组件中需要数据,而且数据在另一个服务器环境下运行,我们就需要跨域请求数据,vue工具中可以使用代理来跨域请求,设置的方法是:在项目的config文件夹中
,打开index.js
,在proxyTable
一项中设置:
- ’/apis’
自定义的代理名
- target
代理的服务器
- changeOrigin
是否允许跨域请求
- pathRewrite
匹配首个页面
// 'http://localhost:7890' 表示的是要跨域请求的地址
// 如果请求的地址是:'http://localhost:7890/index_data'
// 在请求时就可以写成: '/apis/index_data'
'/apis': {
target: 'http://localhost:7890',
changeOrigin: true,
// 我们是以index开头,所以给它清空就好
pathRewrite: {
'^/apis': ''
}
}
杂文:
vue监听回车执行的函数
@keyup.enter.native
弹性:
type="flex"
justify="space-between" // 留有空白的意思
:gutter="20" // gutter的实现方式是设置el-col的style
label 元素内点击文本,就会触发此控件。就是说,当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件上。