- 实例化Vue对象
- 事件及事件修饰符
- 键盘事件、按键修饰符及系统修饰键
- 双向数据绑定
- 计算属性computed
- Class 与 Style 绑定
- v-if 条件渲染
- v-for 列表渲染
- 实战DEMO
- 初始化多个Vue对象
- 初始Vue组件
- Vue - 搭建脚手架CLI
- 介绍SRC文件流程及根组件APP
- Vue 组件嵌套
- 组件 CSS 作用域
- 实战DEMO2
- 属性传值Props(父To子)
- 传值和传引用
- 事件传值(子To父)
- 生命周期(钩子函数)
- 路由和HTTP
实例化Vue对象
<div id="app1">
<h1>{ { name } }</h1>
<p>{ { job } }</p>
<p>{ { sayHi("methods 方法") } }</p>
<a :href="website">logan个人博客</a><br>
<p v-html="websiteTag"></p> <br>
<button @click = "greet">欢迎</button>
</div>
<script>
var app1 = new Vue({
el : "#app1",
data : {
name : "logan",
job : "fronted enginner",
website : "http://logan70.github.io",
websiteTag : "<a href='http://logan70.github.io'>v-html</a>"
},
methods : {
greet: function(){
alert("Hello Vue!")
},
sayHi : function(txt){
return "hello " + this.name + " ! " + txt
}
}
})
</script>
事件及事件修饰符
.stop
阻止冒泡.prevent
阻止默认行为.capture
使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理.self
只当在 event.target 是当前元素自身时触发处理函数,即事件不是从内部元素触发的.once
事件将只会触发一次
<div id="app2">
<h1>Event</h1>
<p>I am { { age } } years old.</p>
<button @click="addAge(1)">大一岁</button>
<button @click="reduceAge(1)">小一岁</button>
<button @dblclick="addAge(10)">双击大十岁</button>
<button @dblclick="reduceAge(10)">双击小十岁</button>
<div id="canvas" @mousemove="updateXY">{ { x } },{ { y } } - <span id="stopMoving" @mousemove.stop>Stop Moving</span></div>
<a href="http://logan70.github.io" @click.prevent>logan个人博客</a>
</div>
<script>
var app2 = new Vue({
el : "#app2",
data : {
age : 25,
x : 0,
y : 0
},
methods : {
addAge : function(num){
this.age += num
},
reduceAge : function(num){
this.age -= num
},
updateXY : function(event){
this.x = event.offsetX;
this.y = event.offsetY;
}
}
})
</script>
键盘事件、按键修饰符及系统修饰键
全部的按键别名:
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
系统修饰键
.ctrl
.alt
.shift
.meta
事件触发时修饰键必须处于按下状态
<div id="app3">
<h1>键盘 Event</h1>
<label for="">姓名:</label>
<input type="text" @keyup="logName">
<label for="">年龄:</label>
<input type="text" @keyup.enter="logAge">
</div>
<script>
var app3 = new Vue({
el : "#app3",
data : {
},
methods : {
logName : function(){
console.log("你正在输入名字")
},
logAge : function(){
console.log("你正在输入年龄")
}
}
})
</script>
双向数据绑定
<div id="app4">
<h1>双向数据绑定</h1>
<label for="">姓名:</label>
<input type="text" @keyup="logName" ref="name" placeholder="edit me">
<span>{ { name } }</span>
<label for="">年龄:</label>
<input type="text" v-model="age" placeholder="edit me">
<span>{ { age } }</span>
</div>
<script>
var app4 = new Vue({
el : "#app4",
data : {
name : "",
age : ""
},
methods : {
logName : function(){
this.name = this.$refs.name.value
console.log("你正在输入名字")
}
}
})
</script>
计算属性computed
-
computed
计算属性是基于它们的依赖进行缓存的。 -
methods
每当触发重新渲染时,调用方法将总会再次执行函数。
<div id="app5">
<h1>计算属性 Computed</h1>
<button @click="a++">Add to A</button>
<button @click="b++">Add to B</button>
<p>A - { { a } }</p>
<p>B - { { b } }</p>
<p>Age + A = { { AgeA } }</p>
<p>Age + B = { { AgeB } }</p>
</div>
<script>
var app5 = new Vue({
el : "#app5",
data : {
a : 0,
b : 0,
age : 35
},
computed : {
AgeA : function(){
return this.age + this.a
},
AgeB : function(){
return this.age + this.b
}
}
})
</script>
Class 与 Style 绑定
<div id="app6">
<h1>动态 CSS Class</h1>
<h2 :class="{ color:changeColor, length:changeLength }" :style="styleObject" @click="changeColor=!changeColor">示例1</h2>
<h2>示例2</h2>
</div>
<script>
var app6 = new Vue({
el : "#app6",
data : {
changeColor : false,
changeLength : false,
styleObject : {
border : "1px solid #000"
}
}
})
</script>
v-if 条件渲染
v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
<div id="app7">
<h1>v-if 条件</h1>
<button @click="error = !error" >Toggle error</button>
<button @click="success = !success">Toggle success</button>
<button @click="isShow = !isShow">Toggle isShow</button>
<p v-if="error">Now you can see me(v-if) (error = true)</p>
<p v-else-if="success">Now you can see me(v-else-if) (success = true && error = false)</p>
<p v-else>Now (error and success) = false</p>
<p v-show="isShow">Now you can see me(v-show) (isShow = true)</p>
</div>
<script>
var app7 = new Vue({
el : "#app7",
data : {
error : false,
success : false,
isShow: false
}
})
</script>
v-for 列表渲染
<div id="app8">
<h1>{ { title } }</h1>
<ul>
<li v-for="character in characters">名字:{ { character } }</li>
</ul>
<ul>
<li v-for="(user,index) in users">{ { index + 1 + "." } } 名字:{ { user.name } } 年龄:{ { user.age } }</li>
</ul>
<template v-for="(user,index) in users">
<p>{ { index + 1 } } . { { user.name } }</p>
<p>{ { user.age } }</p>
</template>
<template v-for="user in users">
<ul>
<li v-for="(value,key,index) in user">{ { index } }-{ { key } }-{ { value } }</li>
</ul>
</template>
</div>
<script>
var app8 = new Vue({
el : "#app8",
data : {
characters : ["logan","leo","nancy"],
users : [
{ name:"henry",age:"25" },
{ name:"jack",age:"20" },
{ name:"tom",age:"23" }
],
title : "v-for 循环"
}
})
</script>
实战DEMO
<!-- 根容器 -->
<div id="vue-app">
<!-- 图片容器,根据ended的变化动态改变class -->
<div id="bag" :class="{ broken: ended }"></div>
<!-- 进度条容器,根据progress变化动态改变红条长度 -->
<div id="progress">
<div :style="{ width: progress + '%' }"></div>
</div>
<!-- 按钮组,点击减少/重置progress -->
<div id="btn-group">
<button @click="punch" v-show="!ended">可劲儿砸</button>
<button @click="restart">重新开始</button>
</div>
</div>
var vm = new Vue({
el : "#vue-app",
data : {
progress : 100,
ended : false
},
methods : {
punch : function(){
this.progress -= 10;
if (this.progress <= 0) {
this.ended = true;
}
},
restart : function(){
this.progress = 100;
this.ended = false;
}
}
})
初始化多个Vue对象
<div id="app9">
<h1>初始化多个Vue实例对象</h1>
<button @click="changeTitle">改变v-for标题</button>
</div>
<script>
var app9 = new Vue({
el : "#app9",
data : {
},
methods : {
changeTitle :function(){
app8.title = "已经改名了";
}
}
})
</script>
初始Vue组件
<div id="app10">
<greeting></greeting>
<greeting></greeting>
</div>
<script>
Vue.component("greeting",{
template : `<p>
{ { name } },初识Vue组件(模板)
<button @click="changeName">改名</button>
</p>`,
data : function(){
return {
name : "Logan"
}
},
methods : {
changeName : function(){
if (this.name == "Logan") {
this.name = "Lee"
} else {
this.name = "Logan";
}
}
}
})
var app10 = new Vue({
el : "#app10"
})
</script>
Vue - 搭建脚手架CLI
Vue-CLI 脚手架
- 脚手架是通过webpack搭建的开发环境
- 使用ES6语法
- 打包和压缩js为一个文件
- 项目文件在环境中编译,而不是浏览器
- 实现页面自动刷新
搭建过程
# 全局安装 vue-cli
$ npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
# 安装依赖,走你
$ cd my-project
$ npm install
$ npm run dev
介绍SRC文件流程及根组件APP
- assets文件夹:存放图片
- components文件夹:存放组件
- App.vue:根组件
- main.js:
- index.html:入口文件
index.html
=> main.js
=> App.vue
=> HelloWorld.vue
Vue 组件嵌套
全局注册嵌套
// 在main.js内
import Users from './components/Users'
// 全局注册组件
Vue.component('users',Users)
局部注册嵌套
// 在App.vue内
<script>
// 引入组件
import Users from './components/Users'
export default {
name: 'App',
data(){
return {
msg : '这是我的第一个Vue脚手架'
}
},
// 注册组件,将只在父组件模板中可用
components : {
users : Users
}
}
</script>
组件 CSS 作用域
<style scoped>
scoped
表示限制CSS只在自身组件内起作用
不加scoped
则各组件通用此组件的样式
实战DEMO2
App.vue
<!-- 1模板:html结构 -->
<template>
<div id="app">
<app-header></app-header>
<users></users>
<app-footer></app-footer>
</div>
</template>
<!-- 2行为:处理逻辑 -->
<script>
import Users from './components/Users'
import Header from './components/Header'
import Footer from './components/Footer'
export default {
name: 'App',
data(){
return {
msg : '这是我的第一个Vue脚手架'
}
},
components : {
'users' : Users,
'app-header' : Header,
'app-footer' : Footer
}
}
</script>
Users.vue
<template>
<div class="users">
<ul>
<li v-for="user in users" @click="user.show = !user.show">
<h2>{ { user.name } }</h2>
<h3 v-show="user.show">{ { user.position } }</h3>
</li>
</ul>
</div>
</template>
<style scoped>
.users{
width: 100%;
max-width: 1200px;
margin: 40px auto;
}
ul{
padding: 0;
display: flex;
flex-wrap: wrap;
}
li{
flex-grow: 1;
flex-basis: 200px;
padding: 40px 0;
margin: 20px;
border: 1px solid #222;
box-sizing: border-box;
text-align: center;
list-style: none;
}
</style>
属性传值Props(父To子)
- 先在父组件内定义要传的值
data(){
return {
users : [
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false }
]
}
},
- 在父组件内插入子组件的地方传入值
<template>
<div id="app">
<app-header></app-header>
<users :users="users"></users>
<app-footer></app-footer>
</div>
</template>
- 在子组件内通过
props传值
export default {
name: 'users',
props : ['users'],
data: function(){
return {
}
}
}
- prop验证(推荐写法)
export default {
name: 'users',
props : {
users : {
type : Array,
required : true
}
},
data: function(){
return {
}
}
}
传值和传引用
传值:(Number,String,Boolean),在子组件内对其进行改变时,其他组件内不会发生变化
传引用:(Array,Object),在子组件内对其进行改变时,其他组件内会发生变化
不应该在子组件内部改变 prop。正确做法是
- Prop 作为初始值传入后,子组件想把它当作局部数据来用
// 定义一个局部变量,并用 prop 的值初始化它:
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
- rop 作为原始数据传入,由子组件处理成其它数据输出。
// 定义一个计算属性,处理 prop 的值并返回:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
事件传值(子To父)
- 第一步:在子组件内触发事件
<template>
<header>
<h1 @click="changeTitle">{ { tittle1 } } { { title } }</h1>
</header>
</template>
methods : {
changeTitle : function(){
// 在子组件内触发事件
this.$emit('titleChanged','通过事件子传父')
}
}
- 第二步:在父组件内接受事件及参数
<template>
<div id="app">
<!-- 在父组件内接受事件及参数 -->
<app-header :title="title" @titleChanged="changeTitleFn($event)"></app-header>
<users :users="users"></users>
<app-footer :title="title"></app-footer>
</div>
</template>
- 第三步:在父组件内定义事件函数
methods : {
changeTitleFn : function(title){
this.title = title
}
}
生命周期(钩子函数)
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
<p>{ { message } }</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message : "xuxiao is boy"
},
beforeCreate: function () {
console.group('beforeCreate 创建前状态===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message)
},
created: function () {
console.group('created 创建完毕状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 挂载前状态===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 挂载结束状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
updated: function () {
console.group('updated 更新完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed: function () {
console.group('destroyed 销毁完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
</script>
</body>
</html>
create 和 mounted 相关
咱们在chrome浏览器里打开,F12看console就能发现
- beforecreated:el 和 data 并未初始化
- created:完成了 data 数据的初始化,el没有
- beforeMount:完成了 el 和 data 初始化
- mounted :完成挂载
beforeMount
阶段el
还是 { { message } }
,这里就是应用的 Virtual DOM
(虚拟Dom)技术,先把坑占住了。到后面mounted
挂载的时候再把值渲染进去。
mounted
内的方法执行完后页面显示
update 相关
数据发生改变时,将会触发update的操作。
updated
内的方法执行完后更新内容显示
destroy 相关
执行了destroy操作,原先生成的dom元素还存在,但是后续DOM就不再受vue控制了。
路由和HTTP
路由
1.路由的安装
npm install vue-router
2.在main.js中安装路由功能
import VueRouter from 'vue-router'
Vue.use(vueRouter)
3.配置路由
const router = new VueRouter({
routes : [
{ path:'/',component:Home }
{ path:'/helloworld',component:HelloWorld }
]
})
4.引入组件
import HelloWorld from './comonents/HelloWorld'
import Home from './comonents/Home'
5.创建挂载根实例
/* eslint-disable no-new */
new Vue({
router,
el: '#app',
components: { App },
template: '<App/>'
})
6.添加html结构
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
7.去除路径中#号
在main.js中router实例中配置
const router = new VueRouter({
routes : [
{ path:'/',component:Home },
{ path:'/helloworld',component:HelloWorld }
],
mode : 'history'
})
8.加入<router-link>
导航
<template>
<div id="app">
<ul>
<li><router-link to="/">Home</router-link></li>
<li><router-link to="/helloworld">Hello</router-link></li>
</ul>
<router-view></router-view>
</div>
</template>
http
使用vue-resource
1.安装vue-resource
npm install vue-resource --save-dev
2.在main.js中安装
import VueResource from 'vue-resource'
Vue.use(VueResource)
3. Home.vue
中添加created
钩子函数 请求http
created(){
this.$http.get('http://jsonplaceholder.typicode.com/users').then((data) => {
// console.log(data)
this.users = data.body
})
}
4.在user.vue
中添加html结构
<template>
<div class="users">
<ul>
<li v-for="user in users" >
<h2>{ { user.name } }</h2>
<h3>{ { user.email } }</h3>
</li>
</ul>
</div>
</template>