一堆数据放在那里是不会有任何作用的,它必须通过我们的View Model(视图模型)才能操控视图。
图中的model其实就是数据,一般我们写成js对象的格式;
中间的这个所谓View Model,就是
var vm = new Vue({
el: '#app', //数据监听
data: {
message: 'Hello Vue!' //数据绑定
}
})
我们把数据放到了vm里,然后把各种directive(命令)放到视图里,这样我们就可以以vm为媒介,通过改变数据来改变视图。
vm实际上是Vue这个类的一个实例,非常容易混淆的是,你会很容易的以为
vm.el == '#app';
vm.data== { message: 'Hello Vue!' };
vm.data.message =='Hello Vue!';
实际上这都是错误的,以上虽然是错误的写法,有时候我们还是希望获得这些属性的,通过vm你需要这样写:
vm.$el === document.getElementById('app') //结果为true
vm.$data.message ==='Hello Vue!' //结果为true
这个$符代表的就是vm的真实属性了。
代码示例:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app">
div>
body>
<script>
let obj ={
message: "hello vue"
} ;
let vm = new Vue({
el: "#app",
data: obj
});
//vm是vue是实例对象
console.log(vm.el)
console.log(vm.el===document.getElementById("app")); //false
console.log(vm.data===obj); //false
console.log(vm.data); //undefined
//console.log(vm.data.message==="hello vue"); //报错
//要想获取 vue实例对象获取传入的对象数据 ,需要传入的属性名前加一个$符号,例如vm.$el vm.$data vm.$methods
console.log(vm.$el==="#app"); //false
console.log(vm.$el===document.getElementById("app")); //true
console.log(vm.$el); //div的dom对象
console.log(vm.$data===obj); //true
console.log(vm.$data); //创建vue对象时,传入的data对应的对象
console.log(vm.$data.message==="hello vue"); //true
script>
html>
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({
data: { a: 1 },
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title>
<script type="text/javascript" src="js/v2.6.10/vue.js" >script>
head>
<body>
<div id="app">
<input type="text" v-model="message" />
div>
<div id="app1">
<input type="text" v-model="message" />
div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
message:"hello world"
},
beforeCreate:function(){
//this指向创建的实例,还不能访问data/computed/methods
console.log("Vue对象创建前状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
},
created:function(){
// 可以访问data、methods,但是未挂载到dom,并且还不能访问$el属性,$ref属性内容此时为空数组
console.log("Vue对象创建完毕状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
this.message="hello 不 world";
},
beforeMount:function(){
//仍为原始el值(app,未挂载前的el修改没有影响后来)
console.log("Vue对象挂载前状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
//this.$el=document.getElementById("app1");//此处挂载后不会再次挂载
console.log(this.$el);
},
mounted:function(){
//挂载后进行修改
console.log("Vue对象挂载之后状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
this.$el=document.getElementById("app1");
console.log(this.$el);
},
beforeUpdate:function(){
console.log("Vue对象更新前状态======");
console.log("el=" +this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
console.log(this.$el);
},
updated:function(){
console.log("Vue对象更新完成状态======");
console.log("el=" +this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
console.log(this.$el);
},
beforeDestroy:function(){
console.log("Vue对象销毁前状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
console.log(this.$el);
},destroyed:function(){
console.log("Vue对象销毁完成状态======");
console.log("el=" + this.$el);
console.log("data=" + this.$data);
console.log("message=" + this.message);
}
})
app.$destroy();
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="js/v2.6.10/vue.js" type="text/javascript">script>
head>
<body>
<div id="app"> div>
body>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
// 挂载点,可认为是element的简写,创建一个vue实例得知道是在哪一块 元素上创建Vue实例,对哪一块视图进行操作
data: {},
// 又称内部数据,该属性值可以是对象,也可以是函数,但优先推荐使用函数,对象里的函数又称方法。
// 并且若是组件中的data则必须使用函数。数据成员,在.vue组件中data是一个函数,要写成data () {}这种方式
props: {} ,
// 又称外部数据,一般用于组件中接受外来传递的数据,在组件使用时,通过标签全局属性的方式进行传参
computed: {
// 计算属性
// 计算属性名:
function(){..} },
watch: {
// 监视属性
},
methods: {
// 成员方法
// 方法名:
function(){..}
},template: "" ,
// 模板
beforeCreate: function() {
// 生命构造函数,还有其他7个...
},compontents: { },
// 其他option....
})
script>
html>
1.1 el:"#id"
, //DOM成员
提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。
1.2 template:" "
, //DOM成员
一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发 slot
1.3 render: (h)=>{h(App)}
, //DOM成员
字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。
1.4 data //数据成员
data():{ return{ } }
,
Vue实例的数据对象。Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化
1.5 methods //方法成员
methods:{ func(){ } }
methods将被混入到 Vue 实例中,可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用方法中的 this自动绑定为 Vue 实例
1.6 watch //监听属性
watch:{ key:value $route:function (newValue, oldValue) { //监控路由 } }
整个为一个对象,键是需要观察的表达式,值是对应回调函数
1.7 computed //计算属性
computed:{ getTotalCount(){ const totalCount=0; return totalCount; } }
,
vue的计算属性,将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为Vue 实例
1.8 props //父组件传给子组件
props:['counts','ids']
,
用于父子组件的eventbus传值,是数组或对象,props的成员是子组件接收的来自父组件的
数据
1.9 propsData //数据成员
创建实例时传递 props。主要作用是方便测试
1.10 filters //资源
filters('filterName',(input,function(){ return newvalue }))
包含 Vue 实例可用过滤器的哈希表。
1.11 directives //资源
包含 Vue 实例可用指令的哈希表。
1.12 components //组件
(即该组件的子实例)这里是包含 Vue 实例可用组件的哈希表。
1.13 name //杂项
允许组件模板递归地调用自身。注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的name。
1.14 parent //杂项
指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用 this.$parent 访问父实例,子实例被推入父实例的 $children 数组中。
1.15 mixins //杂项
mixins 选项接受一个混合对象的数组。Mixin钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
1.16 extends //杂项
允许声明扩展另一个组件。这主要是为了便于扩展单文件组件。这和 mixins 类似,区别在于,组件自身的选项会比要扩展的源组件具有更高的优先级。
1.17 delimiters //杂项
改变纯文本插入分隔符。
1.18 functional //杂项
使组件无状态(没有 data )和无实例(没有 this 上下文)。他们用一个简单的 render 函数返回虚拟节点使他们更容易渲染。
vue.js中创建组件有三个步骤:定义组件,注册组件以及使用组件
定义组件:
- 方式1:先创建一组件构造器,然后由组件构造器创建组件。如:
var myCom = Vue.extend({})
- 方式2:使用Vue.component()直接创建组件。
定义组件名的方式有两种:
- 使用 kebab-case:使用 kebab-case (短横线分隔命名) 定义一个组件(kebab发音/kI’ba:b/)
- 使用 PascalCase:(驼峰式命名) 定义一个组件
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如
。
当使用 PascalCase (驼峰式命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说和
都是可接受的。
全局组件||局部组件
通过选项components定义,但只能在当前Vue实例中使用
将组件内容放到
中引用。
注意:template组件中,有且只有一个根元素
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app1">
<global-componet-a>global-component-a>
div>
<div id="app2">
<global-componet-a>global-componet-a>
div>
<div id="app3">
<global-componet-a>global-componet-a>
<componet-a>componet-a>
div>
<template id="my-template-1">
<div>
<h3>{{info}}h3>
<a href="http://www.baidu.com">去百度a>
div>
template>
<script>
Vue.component("global-componet-a",{
data(){
return{
info:"全局组件"
}
},
template:"#my-template-1"
});
var app1=new Vue({
el:"#app1"
})
var app2=new Vue({
el:"#app2"
})
var app3=new Vue({
el:"#app3",
//局部组件定义和注册,使用范围只能在app3挂载的DOM对象中
components:{
"componet-a":{
data(){
return {
info:"局部组件"
}
},
template:"#my-template-1"
}
}
})
script>
body>
html>
在一个组件内部定义另一个组件,称为父子组件。
子组件只能在父组件内部使用。
默认情况下,子组件无法访问父组件中的数据,每个组件实例的作用域是独立的。
在调用子组件时,绑定想要获取的父组件中的数据在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据。即父组件通过props向下传递数据给子组件。
注:组件中的数据存在方式共有三种:data、props、computed
props传递数据两种形式:
数组方式: props:[‘msg’, ‘username’, ‘age’, ‘userObj’]
对象方式:该方式提供了对数据的校验、类型监测、默认值设置操作。
**prop命名,可以在在组件中使用 postTitle (驼峰名称),在html中是使用短横线命名 post-title **
Vue.component('blog-post', {
// 在 JavaScript 中是 驼峰命名的
props: ['postTitle'],
template: '<h3>{{ postTitle }}h3>'
})
<blog-post post-title="hello!">blog-post>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title>
<script type="text/javascript" src="js/v2.6.10/vue.js" >script>
head>
<body>
<div id="app">
<p>{{message}}p>
<component-a :aaa-message="message">component-a>
div>
<template id="my-template-1">
<div>
<p>子组件以外的message的值{{aaaMessage}}p>
<p>子组件本身的message的值{{childrenmessage}}p>
div>
template>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
message:"fatherBox"//父组件中的值
},
components: {
"component-a":{
data(){
return{
childrenmessage:"son-Box"
}
},
props:["aaaMessage"], //定义props属性对象(数组)
template:"#my-template-1" //使用模板
}
},
})
script>
body>
html>
vm.$emit(事件名,数据)
触发一个自定义事件,事件名自定义。DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app">
<component-a @itemclick="parentclick">component-a>
div>
body>
<template id="my-temlate-1">
<div>
<input type="button" v-for="item in categories" :value="item.name" @click="btnclick(item)" />
div>
template>
<script type="text/javascript">
var componentA={
data:function() {
return {
categories:[
{id:1,name:"家电"},
{id:2,name:"玩具"},
{id:3,name:"数码"},
{id:4,name:"服装"} ,
] ,
}
},
template: "#my-temlate-1",
methods: {
btnclick: function(item) {
//alert(item.id);
//子组件向父组件发出自定义事件(自定义事件名称,自定义事件参数)
//itemclick注意大小写,在html是不区分大小写的,所以这里不能使用驼峰,保持大小写一致,或者使用短横线方式 item-click
this.$emit("itemclick",item);
}
} ,
}
var app = new Vue({
el:"#app",
//注册局部子组件
components:{
"component-a":componentA,
},
methods:{
parentclick:function(item){
//可以获取子组件传过来的参数item
alert("我是父组件,子组件id="+item.id);
} ,
} ,
});
script>
html>
//实例Vue实例作为中央事件总线
var Event=new Vue();
//发送事件
Event.$emit(事件名,数据);
//监听事件
Event.$on(事件名,data => {});
假设兄弟组件有三个,分别是 A、B、C 组件,C 组件如何获取 A 或者 B 组件的数据:
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app">
<my-a>my-a>
<my-b>my-b>
<my-c>my-c>
div>
<template id="a">
<div>
<h3>A:{{name}}h3>
<input type="button" @click="send" value="将数据发送给C组件" />
div>
template>
<template id="b">
<div>
<h3>B:{{age}}h3>
<input type="button" @click="send" value="将数据发送给C组件" />
div>
template>
<template id="c">
<h3>组件C{{name}}-----{{age}}h3>
template>
<script>
var Event=new Vue();//实例Vue实例作为中央事件总线
new Vue({
el:"#app",
components:{
"my-a":{
data(){
return{
name:"aaa"
}
},
template:"#a",
methods: {
send() {
Event.$emit("data-a",this.name)//发送事件
}
},
},
"my-b":{
data(){
return{
age:30
}
},
template:"#b",
methods:{
send() {
Event.$emit("data-b",this.age)//发送事件
}
}
},
"my-c":{
data(){
return{
name:"",
age:0
}
},
template:"#c",
mounted(){
Event.$on("data-a",name=>{
this.name=name
});//监听事件
Event.$on("data-b",age=>{
this.age=age
});
}
}
}
})
script>
body>
html>
props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来,即子组件中使用的父组件数据发生变化,无法传导给父组件。而且不允许子组件直接修改父组件中的数据,会直接报错,这样更有利于组件间的解耦。
解决方式:
方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据。
方式2:如果子组件想修改数据并且同步更新到父组件,可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐使用。
单个组件的过滤器,也叫做局部过滤器。
vue实例全局的过滤器,它可以被应用在任何地方。
{{ message | filterA }}
双括号插值内
v-bind绑定的值的地方{{ message }}
过滤器也可以使用多个,会依次执行。例如: {{ message | filterA |filterB }}
这个例子中会把message 的当做参数传入A过滤器进行过滤,A过滤器过滤完的数据返回值会传入B过滤器。
全局过滤器:Vue.filter(“过滤器名称”,函数);
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script type="text/javascript" src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app1">
<h1>我是app1:{{message | upperCase}}h1>
div>
<div id="app2">
<h1>我是app2: {{message | upperCase}}h1>
div>
body>
<script type="text/javascript">
//定义全局过滤器
Vue.filter("upperCase",
function(value){
if(!value) return "";
value = value.toString();
//字符转换成大写
return value.toUpperCase();
});
var app1 = new Vue({
el:"#app1",
data:{message:"HelloWord" } ,
});
var app2 = new Vue({
el:"#app2",
data:{message:"hahahaha" } ,
});
script>
html>
效果展示:
局部过滤器:定义局部的过滤器 定义格式:fliters:{过滤器名称:函数}
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script type="text/javascript" src="js/v2.6.10/vue.js">script>
head>
<body>
<div id="app3">
<component-a :msg="message">component-a>
div>
body>
<template id="my-temlate-1">
<h3>我是子组件,使用了局部过滤器{{msg|capitalize}}h3>
template>
<script type="text/javascript">
//定义组件
var componentA = {
props:["msg"],
template:"#my-temlate-1",
//定义局部过滤器,注意是filters
filters:{
//过滤器名称:函数
capitalize:function(value){
if(!value) return "";
value = value.toString();
value = value.charAt(0).toUpperCase()+value.substring(1);
// 首字母大写
return value; } ,
} ,
}
var app3=new Vue({
el:"#app3",
data:{message:"ddddd" },
components:{ "component-a":componentA ,
//注册局部组件
} ,
});
script>
html>
vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现。axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护。
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。本质上也是对原生XH(XmlHttpRequest)的封装,只不过它是Promise 的实现版本,符合新的ES规范,有如下特点:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON 数据
客户端支持防御 XSRF
axios({options})
axios.get(url,{options});
GET传参方式:
1.通过url传参
2.通过params选项传参
POST传参方式:axios.post(url,data,{options});
默认情况下,axios将JavaScript对象序列化为JSON。要以application / x-www-form-urlencoded格式发送数据,您可以使用以下选项之一。
传参方式:
1.自己拼接为键值对
2.使用transformRequest,在请求发送前将请求数据进行转换
3.如果使用模块化开发,可以使用qs模块进行转换
Vue中axios中箭头函数的this和function(response)函数体中的this的区别:
1、在methods下的函数this指向的是当前创建的vue实例。
2、axios与后台交互后回调函数的内部的this指向window而并非指向当前的vue实例。
3、若想拿到后台回传的数据更新data里的数据,不能在回调函数中直接使用this,要用外部函数定义的变量(如:_this)存储的this,也就是当前vue的实例。
4、使用箭头函数之后,箭头函数指向的函数内部的this已经绑定了外部的vue实例了。