一、Vue是什么
- MVVM:view、viewModel、Model
- 核心:数据绑定、组件化
- 实现原理:Object.defineProperty()
<body>//双向绑定的实现
<div id="app">
<input type="text" id="txt">
<p id="show-txt"></p>
</div>
<script>
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show-txt').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
</script>
</body>
二、Vue的使用
- 数据驱动
<div id="app">
公众号:{{ name }}
</div>
<script>
let vm = new Vue({
el:"#app",
data:{
name:"web前端教程",
}
});
</script>
- 双向绑定:v-model(用户在页面上做了一些操作,也很方便地实现更新model层的数据。)
<div id="app">
<input v-model="number">
<p>数字:{{ number }}</p>
</div>
<script>
let vm = new Vue({
el:"#app",
data:{
number:"",
}
});
</script>
- 组件
<div id="app"> <card></card> <card></card> <card></card> </div> <script> //注册一个名叫card的组件 Vue.component('card',{ template:`<div> <img src="logo.png" alt=""> <h2>web前端教程</h2> <p>这里是描述,很长的描述</p> <button>我是按钮</button> </div>` }); new Vue({ el:"#app" }); </script>
三、定义一个vue实例的4个常用选项
- filters 过滤器
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
num1:33.141,
num2:46.212,
num3:78.541
},
//过滤器
filters:{
toInt(value){
return parseInt(value);
}
}
});
<div id="app">
数字1:{{ num1 | toInt}}<br>
数字2:{{ num2 | toInt}}<br>
数字3:{{ num3 | toInt}}
</div>
- computed 计算属性
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
num1:1,
num2:3,
num3:6
},
//计算属性
computed:{
sum(){
return this.num1+this.num2+this.num3
}
}
});
<div id="app">
总和:{{ sum }}
</div>
sum的值是依赖data中的数据num1,num2,num3的,一旦它们发生了变化,sum的值也会自动更新。
- methods 方法
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
a:0
},
//方法
methods:{
plus(){
return this.a++;
}
}
});
<div id="app">
{{ a }}
<button v-on:click="plus">加1</button>
</div>
- watch 观察
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
a:0
},
//方法
methods:{
plus(){
return this.a++;
}
},
//观察
watch:{
a(){
console.log(`有变化了,最新值:`);
console.log(this.a);
}
}
});
第四节:轻松掌握 vue 实例的生命周期
掌握实例生命周期的8个阶段:创建、挂载、更新、销毁
1. beforeCreate:此时的实例中的data和el还是undefined,不可用的。
2. created:此时,我们能读取到数据data的值,但是DOM还没生成,所以属性el还不存在,输出$data为一个Object对象,而$el的值为undefined。
3. beforeMount:此时的$el不再是undefined,而是成功关联到我们指定的dom节点<div id=”app”></div>,但此时{{ name }}还没有被成功地渲染成我们data中的数据。
4. mounted:此时打印属性el,我们看到{{ name }}已经成功渲染成我们data.name的值:“前端君”。
5. beforeUpdate:
7. beforeDestroy:调用实例的destroy( )方法可以销毁当前的组件,在销毁前,会触发beforeDestroy钩子。
8. destroyed
9. actived
keep-alive组件被激活的时候调用。
10. deactivated
keep-alive 组件停用时调用。
第五节:教你如何在html中绑定数据
- Mustache语法
- 绑定纯html:v-html
<div id="app" v-html="name"></div>
<script>
let app = new Vue({
el:"#app",
data:{
name:"<strong>前端君</strong>"
}
});
</script>
- 绑定属性:v-bind
<div id="app">
<!--在href前用v-bind:修饰-->
<a v-bind:href="link">hello官网</a>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
link:"http://hello.com"
}
});
</script>
<!--缩写-->需要注意的是:当渲染的属性值是布尔值的时候( true 和 false ),效果就不一样了,并不是简单地将 true 或者 false 渲染出来,而是当值为 false 的时候,属性会被移除。
<a :href="link">hello官网</a>
- 支持javascript表达式
1.加减乘除运算:
<div id="app">{{ num+3 }}</div>
2.三元运算符:
<div id="app">{{ ok ? 'yes':'no' }}</div>
3.字符串拼接:
<a :href="'http://'+host">hello官网</a>
第六节:实战前必须掌握的10个指令(上)
1. v-text 指令:指令用于更新标签包含的文本,它的作用跟双大括号的效果一样。2. v-html 指令
3. v-show 指令: v-show 指令的取值为true/false,分别对应着显示/隐藏。
v-show设置为false,元素解析成:
<p style="display: none">我是false</p>
4. v-if 指令: v-if 指令的取值也是为true或false,它控制元素是否需要被渲染出来
如果需要频繁切换显示/隐藏的,就用 v-show ;如果运行后不太可能切换显示/隐藏的,就用 v-if 。
5. v-else 指令
第七节:实战前必须掌握的10个指令(下)
6. v-for 指令<div id="app">
<div v-for="item in list">{{item}}</div>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
list:['Tom','John','Lisa']
}
});
</script>
<div id="app">
<div v-for="(item,index) in list">
{{index}}.{{item}}
</div>
</div>
提醒:v-for指令除了可以迭代数组,还可以迭代对象和整数。
7. v-bind 指令:用于动态绑定DOM元素的属性,比较常见的比如:<a>标签的href属性,<img/>标签的src属性。
8. v-on 指令: v-on 指令相当于绑定事件的监听器,绑定的事件触发了,可以指定事件的处理函数,
<div id="app">
<button v-on:click="say('Tom')">
点击
</button>
</div>
<script>
let app = new Vue({
el:"#app",
methods:{
say(name){
console.log('hello,'+name);
}
}
});
</script>
9. v-model
指令:这是一个最重要最常用的指令,一般用在表单输入,它帮助我们轻易地实现表单控件和数据的双向绑定
10. v-once 指令:我们再来讲解一下v-once指令,它的特点是只渲染一次,后面元素中的数据再更新变化,都不会重新渲染
<div id="app">
<input v-model="msg" type="text">
<p v-once>你输入:{{ msg }}</p>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
msg:'hello,公众号的同学们'
}
});
</script>
第八节:掌握vue的另一个核心:组件
<div id="app">
<my-article v-for="item.articles" :detail="item"></my-article>
</div>
<script>
Vue.component('my-article',{
props:['detail'],
template:`<div>
<div>
<h1>{{detail.title}</h1>
<div>
<span>{{detail.date}}</span>
<span v-show="detail.is_original">原创</span>
</div>
</div>
<img :src="detail.cover_url" alt="">
</div>`
});
let vm = new Vue({
el:"#app",
data:{
article:{
title:"第一节:Vue.js框架是什么,为什么选择它?",
date:" 2017年03月06日",
is_original:true,
cover_url:"cover.jpg"
},
{
title:"第二节:简易安装 和 快速入门Vue.js",
date:" 2017年03月09日",
is_original:true,
cover_url:"cover.jpg"
},
} }); </script>
第九节:实现vue组件之间的通信
- 父组件→子组件:props是单向绑定的(父→子),是vue为了防止子组件无意修改了父组件的数据和状态,如果多个子组件任意地对父组件进行修改,这会让这很整个应用的数据流难以阅读。如果你想修改父组件传过来的数据,最好是定义一个局部的变量,来依赖传过来的数据。
- 子组件→父组件:自定义事件。
<div id="app">
<son @connect="say"></son>
</div>
Vue.component('son',{
template:`<button @click="send">
点击
</button>`,
data(){
return{
msg:'大家好,我是子组件的数据'
}
},
methods:{
send(){
this.$emit('connect',this.msg);
}
});
const app = new Vue({
el:"#app",
methods:{
say(msg){
console.log(msg);
}
}
});
- 非父子组件通信:除了父子组件的相互通信,非父子关系的组件该如何通信,我们可以巧妙地利用一个空的vue实例来作为一个中央事件总线。
第十一节:动态绑定class和style
1.绑定class
- 对象语法
<div id="app">
<p :class="{'active':isActive}">这是文字</p>
</div>
<script>
//创建一个实例vm
const vm = new Vue({
el:"#app",
data:{
isActive:true
}
});
</script>
- 数组语法
<p :class="[activeClass,errorClass]"> 这是文字 </p> data:{ activeClass:'active', errorClass:'error' }
2.绑定内联样式style
<p :style="{color:colorStyle}">
这是文字
</p>
data:{
colorStyle:'red'
}
第十二节:用transition组件轻松实现过渡效果
除了CSS3的transition属性,Vue提供的组件也叫transition,可别混淆了,它们是两个不同的东西,仅仅是长得一样罢了。
Vue提供的 <transition/> 组件,会在下列四种情况下起作用:
1. 条件渲染(使用v-if)
2. 条件展示(使用了v-show)
3. 动态组件
4. 组件根节点
过渡原理分析
原来,当一个被 <transition/> 组件包含的节点出现了以上的4种情况的任意一种的时候,Vue自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
所谓的:“在恰当的时机添加/删除 CSS 类名”,其实是:
1.v-enter:进入过渡效果(enter)刚刚开始那一刻。在元素被插入或者show的时候生效,在下一个帧就会立刻移除,一瞬间的事。
2.v-enter-active: 表示进入过渡(entering)的结束状态。在元素被插入时生效,在 transition/animation 完成之后移除。
3.v-leave: 离开过渡(leave)的开始那一刻。在离开过渡被触发时生效,在下一个帧移除,也是一瞬间的事。
4.v-leave-active:离开过渡(leaving)的结束状态。在离开过渡被触发时生效,在 transition/animation 完成之后移除。
进入过渡:
离开过渡:
<div id="app" class="app">
<button
@click="showBox = !showBox"
class="btn">
切换</button>
<div class="container">
<transition name="box">
<div v-show="showBox" class="box">
i am the box
</div>
</transition>
</div>
</div>
比如,当它进入过渡的时候(隐藏→显示),就会依次发生:
1. 添加.box-enter
2. 删除.box-enter,添加 .box-enter-active
3. 删除.box-enter-active
当它离开过渡的时候(显示→隐藏),就会依次发生:
1. 添加.box-leave
2. 删除.box- leave,添加 .box- leave-active
3. 删除.box- leave -active
第十三节、vue-router10分钟快速入门
对于SPA ( single page application 单页面应用),尤其是做移动端的网页应用,由于使用 <a/> 标签实现页面的切换和跳转,会有一定的加载时间消耗。
将网页应用做成一个SPA单页面应用,用视图切换(隐藏和显示)来模拟页面的切换。而但你的项目使用了vue进行开发,那么在实现视图切换的时候,你就可以借助vue-router来帮助你方便地实现视图切换。
将网页应用做成一个SPA单页面应用,用视图切换(隐藏和显示)来模拟页面的切换。而但你的项目使用了vue进行开发,那么在实现视图切换的时候,你就可以借助vue-router来帮助你方便地实现视图切换。
第1步:安装vue-router
创建一个页面,安装引入vue.js和vue-router.js。
你可以使用:直接下载/CND或者NPM进行安装,我们这里用最简单的方式安装:把文件都下载到本地,直接引入。
<script src="js/vue2.0.js"></script>
<script src="js/vue-router.js"></script>
第2步:准备组件
<router-link/> 组件用于帮助用户进行视图导航,也就是我们传统的 <a/> 标签经常做的事。 <a/> 标签用href属性来指定导航的目标地址,而 <router-link/> 组件则用to属性来指定目标地址。
<router-view/> 组件负责渲染匹配到的视图组件,也就是渲染<router-link>指向的目标地址。
<div id="app">
<!--使用 router-link 组件来导航.-->
<!-- 通过传入 `to` 属性指定链接. -->
<div class="nav">
<router-link to="/vue">
简易vue
</router-link>
<router-link to="/es6">
趣味ES6
</router-link>
<router-link to="/career">
人在职场
</router-link>
</div>
<div class="content">
!--匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</div>
//定义路由对应的组件。(局部注册)
//1.简易vue 对应的视图组件
const vueComponent = {
template:`<div>
这里是《简易vue》教程
</div>`
};
//2.趣味ES6 对应的视图组件
const es6Component = {
template:`<div>
这里是《趣味ES6》教程
</div>`
};
//3.人在职场 对应的视图组件
const careerComponent = {
template:`<div>
《混口饭吃》与《工资待遇》
</div>`
};
要关联起来,我们可以直接创建一个router实例,创建实例的时候我们需要传参数routes来进行配置
const router = new VueRouter({
//配置routes
routes:[
//定义3个导航和组件的映射关系
{
path:"/vue",
component:vueComponent
},
{
path:"/es6",
component:es6Component
},
{
path:"/career",
component:careerComponent
},
]
});
创建一个
vue
实例,创建的时候通过
配置router参数来注入我们刚刚定义好的router路由
。
//创建vue实例,注入路由router
const app = new Vue({
el:"#app",
router //此处是ES6语法,
//相当于router:router
});
第十四节、Vuex
Vuex是一个专为Vue开发的应用程序的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex采用类似全局对象的形式来管理所有组件的公用数据,如果你想想修改这个全局对象的数据?是可以的,但没那么简单,你得按照Vuex提供的方式来修改,不能自己随意用自己的方式来修改。
使用Vuex的好处
1.Vuex的状态存储是响应式的,什么意思呢?就是当你的组件使用到了这个Vuex的状态,一旦它改变了,所有关联的组件都会自动更新相对应的数据,这样开发者省事很多。
2.你不能直接修改Vuex的状态,如果是个全局对象变量,要修改很容易,但是在Vuex中不能这样做,想修改就得使用Vuex提供的唯一途径:显示地提交(commint)mutations来实现修改。这样做的好处就是方便我们跟踪每一个状态的变化,在开发过程中调试的时候,非常实用。
如果你开发的是较大型的应用,出现多个视图组件共同依赖一个状态,这个状态相当于我们的全局对象数据,其他组件的改动,会影响到它,反之,它的修改也需要更新其他关联的组件,那么Vuex就很适用。比如:商城系统,外卖系统等等。
第十五节、Vuex的3个核心概念
- 创建仓库Store
//创建一个 store
const store = new Vuex.Store({});
- 核心:State
Vuex的作用类似全局对象,没错,Vuex 使用单一状态树,用一个对象State包含了整个应用层级的所有状态,你可以理解为这些状态就是一堆全局变量和数据。
/创建一个 store
const store = new Vuex.Store({
//state存储应用层的状态
state:{
count:5 //总数:5
}
});
如果你还是传统的方法,定义一个全局变量来管理这些全局数据,那么就非常不合理,不但不便于调试,而且全局变量容易造成全局污染等问题。
- 核心:Getters
当我们需要从 state 中派生出一些状态的时候,就会使用到 getters ,你可以将 getters 理解 state 的计算属性。
const store = new Vuex.Store({
//state存储应用层的状态
state:{
count:5 //总数:5
},
//派生出来的状态
getters:{
//ES6 的箭头函数语法
newCount:state => state.count * 3
}
});
- 核心:Mutations
Vuex给我们提供修改仓库 store 中的状态的唯一办法就是通过提交mutation。我们来看看如何定义一个mutation,它和上面的 getters ,会接受 state 作为第一个参数:
const store = new Vuex.Store({
//state存储应用层的状态
state:{
count:5 //总数:5
},
//更改store状态的唯一途径
mutations:{
increment(state){
state.count ++;
}
}
});
- 使用
//提交一个名为increment的mutation store.commit('increment');
/... //更改store状态的唯一途径 mutations:{ increment(state,n){ state.count += n; } } //... store.commit('increment',10);
第十六节、demo(简易计算器)
<div id="app">
<div class="result">{{result}}</div>
<div class="enter">{{ enter === ""?0:enter}}</div>
<div class="keys">
<div class="list">
<keyboard
v-for="item in keys"
:value="item">
</keyboard>
</div>
</div>
</div>
const app = new Vue({
//挂载元素
el:"#app",
data:{
//16个按键的值
keys:[
'clear', '+', '-', '*',
'7', '8', '9', '/',
'4', '5', '6', '0',
'1', '2', '3', '=',
]
},
store,
computed:{
result(){
//通过this.$store获取仓库的数据result
return this.$store.state.result;
},
enter(){
//通过this.$store获取仓库的数据result
return this.$store.state.enter;
}
}
});
//定义组件
Vue.component('keyboard',{
props:['value'],
//点击事件的监听处理getKeyboardValue
template:`<div
@click="getKeyboardValue"
:data-value="value">
{{value}}
</div>`,
methods:{
//点击事件处理函数
getKeyboardValue(event){
//获取当前的按键的值
let value=event.target.dataset.value;
//通过commit提交mutation
this.$store.commit('calculate',value)
}
}
});
//创建仓库store
const store = new Vuex.Store({
state:{
result:"",
enter:""
},
//定义名为calculate的mutation
mutations:{
calculate(state,value){
if(value === '='){
//按键的值为=,进行结果计算
state.result = eval(state.enter);
state.enter += value;
}else if(value === 'clear'){
//按键的值为clear,清空数据
state.result = state.enter = "";
}else{
//输入结果enter进行拼接
state.enter += value;
}
}
}
});
第十七节、用axios来实现数据请求,简单易用
axios.get('/detail', {
//参数
params: {
id: 10
}
}).then(function (res) {
//成功获取数据
console.log(res);
}).catch(function (err) {
//请求错误
console.log(err);
});
//执行post请求
axios.post('/add', {
name: '前端君',
age: 26
}).then(function (res) {
//请求成功
console.log(res);
}).catch(function (err) {
//请求失败
console.log(err);
});
多个请求并发
function getProfile(){
//请求1
return axios.get('/profile');
}
function getUser(){
//请求2
return axios.get('/user');
}
//并发请求
axios.all([
getProfile(),
getUser()
]).then(axios.spread((res1, res2)=>{
//两个请求现已完成
console.log(res1);
console.log(res2);
}));
// 发送一个 POST 请求
axios({
method: 'post',
url: '/user',
data: {
name: '前端君',
}
});
除了 axios.get() 和 axios.post() ,axios还为所有支持的请求方式提供了别名。
axios.request()
axios.delete( )
axios.head( )
axios.put( )
axios.patch( )