第一个 Vue 应用
- 导包
官方提供了两个包
-
开发环境版本
-
生产环境版本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
</body>
</html>
- 采用模板语法来声明式地将数据渲染进 DOM 的系统
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
</body>
</html>
- 创建VUE实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</html>
data
基本语法
数据绑定最常见的形式就是使用“Mustache(胡子)”语法 (双大括号) 的文本插值
<span>{{ message}}</span>
Mustache 标签将会被替代为对应数据对象上message
属性的值。无论何时,绑定的数据对象上message
属性发生了改变,插值处的内容都会更新
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<span>{{ message }}</span> <br>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</html>
通过chrome浏览器的快捷键ctrl+shift+i或者F12来展示调试工具
我们也可以通过改变Vue的分隔符来修改Mustache 标签
v-bind绑定元素属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<span>{{ message }}</span> <br>
<span v-bind:title="ads">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span> <br>
<a v-bind:href="home" target="_blank">戳我有惊喜</a>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
ads:'页面加载于 ' + new Date().toLocaleString(),
home:'http://www.itcast.cn/'
}
})
</script>
</html>
v-bind: 简写 :
if条件渲染
通过条件指令可以控制元素的创建(显示)或者销毁(隐藏)
-
v-if
-
v-else-if
-
v-else
-
v-show
v-if
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<span>{{ message }}</span> <br>
<span :title="ads">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span> <br>
<a :href="home" target="_blank" title="惊喜">戳我有惊喜</a> <br>
<p v-if="seen">现在你看到我了</p>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
ads:'页面加载于 ' + new Date().toLocaleString(),
home:'http://www.itcast.cn/',
seen:true,
}
})
</script>
</html>
效果
v-if和v-else
<a href="#" v-if="islogin">个人中心</a>
<a href="#" v-else>登录</a>
v-else要紧跟 v-if后边
v-if,v-else-if和v-else
<img src="" alt="皇帝" v-if="level === 1">
<img src="" alt="皇亲" v-else-if="level === 2">
<img src="" alt="国戚" v-else-if="level === 3">
<img src="" alt="大臣" v-else>
v-show
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p v-if="seen" id="if">现在你看到我了</p>
<p v-show="seen" id="show">现在你看到我了</p>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
seen:false
}
})
</script>
</html>
效果
v-show用法和v-if大致一样,但是它不支持v-else,它和v-if的区别是,它制作元素样式的显示和隐藏,元素一直是存在的
注意在vue中使用v-show, 原来的css代码不能设置display属性, 会导致冲突
for列表渲染
v-for
指令可以绑定数组的数据来渲染一个项目列表
v-for
指令需要使用item in items
形式的特殊语法,items
是源数据数组并且item
是数组元素迭代的别名。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛X项目' }
]
}
})
</script>
</html>
效果
index
<ol>
<li v-for="(todo,index) in todos">
{{ todo.text }}-{{index}}
</li>
</ol>
对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="value in object">
{{ value }}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
</script>
</html>
效果
对象列表
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in items">
{{ item.title }}~~~{{item.author}}~~~{{item.publishedAt}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items: [
{
title: 'Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
},
{
title: 'python',
author: 'Ricky',
publishedAt: '2019-04-10'
},
{
title: 'itcast',
author: 'itcast',
publishedAt: '2006-05-08'
}
]
}
})
</script>
</html>
效果
methods事件
可以用v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
counter:0
}
})
</script>
</html>
效果
事件处理方法
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在v-on
指令中是不可行的。因此v-on
还可以接收一个需要调用的方法名称
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="add">Add 1</button>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
counter:0
},
methods:{
add:function(){
counter+=1
alert(this.counter)
}
}
})
</script>
</html>
事件处理方法传递参数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="addnum(counter)">Add {{counter}}</button>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
counter:1
},
methods:{
addnum:function(num){
this.counter = num+this.counter
alert(this.counter)
}
}
})
</script>
</html>
v-on: 简写 @
model表单输入绑定(双向绑定数据)
-
单行文本框
-
多行文本框
-
单选框
- 多选框
- 下拉框
可以用v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
会忽略所有表单元素的value
、checked
、selected
特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的data
选项中声明初始值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table border="1">
<tr><td>用 户 名</td><td><input type="text" v-model="username" @blur="checkusername"> </td></tr>
<tr><td>密码</td><td><input type="password" v-model="password1"> </td></tr>
<tr><td>确认密码</td><td><input type="password" v-model="password2"></td></tr>
<tr><td>性别</td>
<td>
男<input type="radio" name="sex" value="boy" v-model="sex">
女 <input type="radio" name="sex" value="girl" v-model="sex"></td>
</tr>
<tr><td>爱好</td>
<td>
足球 <input type="checkbox" name="like" value="足球" v-model="like">
篮球 <input type="checkbox" name="like" value="篮球" v-model="like">
兵乓球<input type="checkbox" name="like" value="兵乓球" v-model="like">
</td>
</tr>
<tr><td>所在城市</td>
<td>
<select name="city" v-model="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
</select>
</td>
</tr>
<tr><td>个人简介</td><td><textarea name="desc" v-model="desc"></textarea> </td></tr>
</table>
<button @click="register">注册</button>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
username:'',
password1:'',
password2:'',
sex:'',
like:[],
city:'',
desc:''
},
methods:{
register:function(){
alert(this.username+this.password1+this.password2+this.sex+this.like+this.city+this.desc)
},
checkusername:function(){
alert(this.username)
}
}
})
</script>
</html>
Todolist案例
准备工作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text"> <button>添加</button>
<hr/>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items:['学习Vue','学习Django基础','学习Django前台'],
},
methods:{
}
})
</script>
</html>
列表数据渲染
<ul>
<li v-for="item in items">{{item}}</li>
</ul>
绑定数据能够添加到列表中
<body>
<div id="app">
<input type="text" v-model="newitem"> <button @click="addNetItem">添加</button>
<hr/>
<ul>
<li v-for="item in items">{{item}}</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items:['学习Vue','学习Django基础','学习Django前台'],
newitem:'',
},
methods:{
addNetItem:function(){
this.items.push(this.newitem);
this.newitem='';
}
}
})
</script>
</html>
实现删除功能
<div id="app">
<input type="text" v-model="newitem"> <button @click="addNetItem">添加</button>
<hr/>
<ul>
<li v-for="(item,index) in items">
<span>{{item}}</span>
<a href="javascript:;" @click="deleteItem(index)">删除</a>
</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items:['学习Vue','学习Django基础','学习Django前台'],
newitem:'',
},
methods:{
addNetItem:function(){
this.items.push(this.newitem);
this.newitem='';
},
deleteItem:function(index){
this.items.splice(index,1)
}
}
})
</script>
</html>
添加移动按钮,实现移动功能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="newitem"> <button @click="addNetItem">添加</button>
<hr/>
<ul>
<li v-for="(item,index) in items">
<a href="javascript:;" @click="upItem(index)">↑</a>
<span>{{item}}</span>
<a href="javascript:;" @click="downItem(index)">↓</a>
<a href="javascript:;" @click="deleteItem(index)">删除</a>
</li>
</ul>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
items:['学习Vue','学习Django基础','学习Django前台'],
newitem:'',
},
methods:{
addNetItem:function(){
this.items.push(this.newitem);
this.newitem='';
},
deleteItem:function(index){
this.items.splice(index,1);
},
upItem:function(index){
current=this.items[index];
this.items.splice(index,1);
this.items.splice(index-1,0,current);
},
downItem:function(index){
current=this.items[index];
this.items.splice(index,1);
this.items.splice(index+1,0,current);
}
}
})
</script>
</html>
ES6语法
ES6语法介绍
ES6是JavaScript语言的新版本,它也可以叫做ES2015,之前学习的JavaScript属于ES5,ES6在它的基础上增加了一些语法,ES6是未来JavaScript的趋势,而且vue组件开发中会使用很多的ES6的语法,所以掌握这些常用的ES6语法是必须的。
变量声明
var:它是用来声明变量的。如果在方法中声明,则为局部变量;如果在全局中声明,则为全局变量。
var num=10
变量一定要在声明后使用,否则报错
let:ES6新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
{
let a = 10;
var b = 1;
}
上面代码在代码块之中,分别用let
和var
声明了两个变量。然后在代码块之外调用这两个变量,结果let
声明的变量报错,var
声明的变量返回了正确的值。这表明,let
声明的变量只在它所在的代码块有效。
for
循环的计数器,就很合适使用let
命令。for (let i = 0; i < 10; i++) {} 计数器i只在for循环体内有效,在循环体外引用就会报错。
const:const
声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
Javascript对象的写法
ES5的写法
var person = {
name:'itcast',
age:13,
say:function(){
alert('hello')
}
}
person.say()
还可以写
var person = {};
person.name='itheima';
person.age=13;
person.say = function (){alert('hello')}
person.say();
ES6的写法
需要注意的是, 实现简写,有一个前提,必须变量名属性名一致
//定义变量
var name='itcast';
var age=13;
//创建对象
var person = {
name,
age,
say:function(){
alert('hello');
}
};
//调用
person.say()
ES6的箭头函数
作用:
- 定义函数新的方式
- 改变this的指向
定义函数新的方式
//无参数,无返回值
var say = ()=> {
alert('我是无参数无返回值函数');
}
//有参数,无返回值
var eat = food => {
alert('我喜欢吃'+food);
}
//有参数,有返回值
var total = (num1,num2) => {
return num1+num2;
}
改变this的指向
如果层级比较深的时候, this的指向就变成了window, 这时候就可以通过箭头函数解决这个指向的问题
var person = {
name:'itcast',
age:13,
say:function(){
alert('my name is ' + this.name);
}
}
//调用
person.say()
axios发送ajax请求
准备工程
创建一个django工程,例如 login.创建完成之后,再创建一个子应用,例如users.最后再设置一下模板文件
准备html和html显示
在模板文件中创建一个axios.html,内容如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<span>{{ message }}</span> <br>
<a href="javascript:;">登录</a> <br>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
delimiters:["[[","]]"],
data: {
message: 'Hello Vue!',
},
})
</script>
</html>
创建视图并加载模板的html
#url设置
from django.conf.urls import url
from users.views import ShowLoginView
urlpatterns = [
url(r'^show/$',ShowLoginView.as_view()),
]
#视图
class ShowLoginView(View):
def get(self,request):
return render(request,'axios.html')
导入axios,并发送GET/POST请求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 导入axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<span>{{ message }}</span> <br>
<span>[[ message ]]</span> <br>
<a @click="login" href="javascript:;">登录-GET</a> <br>
<a @click="login2" href="javascript:;">登录-GET2</a> <br>
<a @click="login3" href="javascript:;">登录-POST</a> <br>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
delimiters:["[[","]]"],
data: {
message: 'Hello Vue!',
},
methods:{
login:function(){
let url = 'http://127.0.0.1:8000/login/?username=admin&password=123';
axios.get(url).then(response=>{
if(response.data.code == '200'){
this.message=response.data.info.username;
}else if (response.data.code == '400') {
this.message=response.data.msg;
}
}).catch(error=>{
console.log(error)
})
},
login2:function(){
let url = 'http://127.0.0.1:8000/login/';
axios.get(url,{
params:{
"username":"admin",
"password":"123"
}
}).then(response=>{
if(response.data.code == '200'){
this.message=response.data.info.username;
}else if (response.data.code == '400') {
this.message=response.data.msg;
}
}).catch(error=>{
console.log(error)
})
},
login3:function(){
let url = 'http://127.0.0.1:8000/login/';
axios.post(url,{
"username":"admin",
"password":"123"
}).then(response=>{
if(response.data.code == '200'){
this.message=response.data.info.username;
}else if (response.data.code == '400') {
this.message=response.data.msg;
}
}).catch(error=>{
console.log(error)
})
}
}
})
</script>
</html>
1.因为Vue的模板变量和django的模板变量分隔符冲突,所以需要修改Vue的分隔符
delimiters:["[[","]]"]
2.箭头函数解决这个指向的问题
后台代码
#定义路由
from django.conf.urls import url
from users.views import ShowLoginView, LoginView
urlpatterns = [
url(r'^show/$',ShowLoginView.as_view()),
url(r'^login/$',LoginView.as_view()),
]
#定义视图
class LoginView(View):
def get(self, request):
#获取参数
username = request.GET.get('username')
password = request.GET.get('password')
#验证参数并返回相应
if username == 'admin' and password == '123':
return JsonResponse({'code': 200, 'msg':'ok','info': {'username': username, 'user_id': '666'}})
else:
return JsonResponse({'code': 400,'msg':'账号或密码错误'})
def post(self, request):
# 获取参数
data = json.loads(request.body.decode())
username = data.get('username')
password = data.get('password')
# 验证参数并返回相应
if username == 'admin' and password == '123':
return JsonResponse({'code': 200, 'msg':'ok','info': {'username': username, 'user_id': '666'}})
else:
return JsonResponse({'code': 400,'msg':'账号或密码错误'})
Vue组件
组件(Component)是Vue.js最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。就像是python中封装一个类,在其他类中可以继承和调用类中的属性和方法。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
组件的基本使用
- 全局组件的使用
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 将组件名以标签的形式添加到div中,调用组件中的内容 -->
<zujian_all></zujian_all>
</div>
<script>
// 全局组件通过 Vue.component注册
Vue.component(
'zujian_all',
{ // template指定组件显示的html内容
template:'<div>全局组件</div>',
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
Vue.component()方法中参数说明
第一个参数指定组件名
第二参数以 {} 形式传递,在里面指定组件的属性,template指定组件的要加载的内容
- 局部组件指定
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<zujian_all></zujian_all>
</div>
<script>
// 局部组件注册,定义局部组件
var zujian_a={
template:'<div>局部组件1</div>',
};
// 全局组件
Vue.component(
'zujian_all',
{ // 在全局中调用局部组件
template:'<div>全局组件 <zujian_a></zujian_a> </div>',
// components 将局部组件注册到全局组件中
components:{
zujian_a
}
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
- 多个局部组件的使用
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<zujian_all></zujian_all>
</div>
<script>
// 局部组件注册,定义局部组件
var zujian_a={
template:'<div>局部组件1</div>',
};
var zujian_b={
template:'<div>局部组件2</div>',
};
// 全局组件
Vue.component(
'zujian_all',
{ // 在全局中调用局部组件
template:'<div>全局组件 <zujian_a></zujian_a> <zujian_b></zujian_b> </div>',
// components 将局部组件注册到全局组件中
components:{
zujian_a,
zujian_b
}
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
- 组间的关系
- 组件中可以通过components嵌套另外的组件,比如可以在组件zujian_a中嵌套组件zujian_b
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<zujian_all></zujian_all>
</div>
<script>
// 局部组件注册,定义局部组件
var zujian_b={
template:'<div>局部组件2</div>',
};
var zujian_a={
template:'<div>局部组件1 <zujian_b></zujian_b> </div>',
components:{
zujian_b
}
};
// 全局组件
Vue.component(
'zujian_all',
{ // 在全局中调用局部组件
template:'<div>全局组件 <zujian_a></zujian_a> </div>',
// components 将局部组件注册到全局组件中
components:{
zujian_a
}
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
注意:
如果要进行组件嵌套,则必须先讲嵌套的组件定义出来,否则不生效,比如在组件zujian_a中嵌套zujian_b则必须先将zujian_b定义出来
组件中数据的绑定
在vue中数据通过data属性进行绑定,如下
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
{{name}}
</div>
<script>
new Vue({
el: '#app',
data: {
name:'python'
}
})
</script>
</body>
</html>
在组件中进行数据绑定虽然也是通过data属性,但是对应的值不再是{}json形式,而是一个函数方法。如下
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<zujian_all></zujian_all>
</div>
<script>
// 局部组件注册,定义局部组件
var zujian_a={
template:'<div>局部组件1</div>',
};
// 全局组件
Vue.component(
'zujian_all',
{ // 在全局中使用绑定的数据 {{name}}
template:'<div>全局组件 <zujian_a></zujian_a> {{name}} </div>',
// components 将局部组件注册到全局组件中
components:{
zujian_a,
},
// data属性指定绑定的数据内容,可以在当前的组件中进行使用
data:function(){
return {name:'python'}
}
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
组件传值
父组件给子组件传值,组件中通过props属性传递数据,如下:
<!DOCTYPE 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">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<zujian_all></zujian_all>
</div>
<script>
// 局部组件注册,定义局部组件
var zujian_a={
template:'<div>局部组件1 {{pos}} </div>',
// 在子组件中通过props属性定义接受值的名称
props:['pos']
};
// 全局组件
Vue.component(
'zujian_all',
{ // 在全局组件中调用子组件时,通过v-bind指定子组件中pos接受父组件中的哪个值
template:'<div>全局组件 <zujian_a v-bind:pos="name"></zujian_a> </div>',
// components 将局部组件注册到全局组件中
components:{
zujian_a,
},
// data属性指定绑定的数据内容,可以在当前的组件中进行使用
data:function(){
return {name:'python'}
}
}
)
new Vue({
el: '#app',
})
</script>
</body>
</html>
子组件给父组件传值,通过$emi将数据传递个父组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello Ming</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id='app'>
<zujian_all></zujian_all>
</div>
<script>
var zujian_a={
template:'<div> 局部组件A <button v-on:click="isupload"> 上传</button> </div>',
methods:{
isupload:function(){
this.$emit('isListen','hello') // 子元素上的点击事件成功后,通过 $emit 将事件和数据传递给父组件
}
}
}
Vue.component('zujian_all',{
template:'<div> 全局组件 <zujian_a v-on:isListen="isShow"></zujian_a> </div>',
components:{
zujian_a
},
methods:{
isShow:function(data){
alert(data) //data参数接受子组件传递的值
}
}
})
new Vue({
el:'#app'
})
</script>
</body>
</html>
单文件组件
将一个组件相关的html结构,css样式,以及交互的JavaScript代码从html文件中剥离出来,合成一个文件,这种文件就是单文件组件,相当于一个组件具有了结构、表现和行为的完整功能,方便组件之间随意组合以及组件的重用,这种文件的扩展名为“.vue”,比如:"breadcrumb.vue"。
// 使用template标签来定义html部分
<template>
<div :class="{crumb:true,hot:isHot}" @click="isHot=!isHot">
当前位置是:{{ pos }}
</div>
</template>
// javascript要写成模块导出的形式:
<script>
export default{
props:['pos'],
data:function(){
return {
isHot:false
}
}
}
</script>
// 样式中如果有scope关键字,表示这些样式是组件局部的,不会影响其他元素
<style scoped>
.crumb{
width:90%;
line-height:50px;
margin:0px auto;
border-bottom:1px solid #ddd;
}
.hot{
color:red;
font-weight:bold;
text-indent:10px;
}
</style>
环境配置
单文件组件不能直接运行使用,需要依赖node项目对其进行解析打包,在使用之前需要先进行环境配置
-
安装node版本管理工具nvm
-
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash // 更新配置 source .bashrc
-
-
安装最新版本的node
-
nvm install node
-
-
更新npm的安装源
-
npm config set registry https://registry.npm.taobao.org
-
-
创建项目目录
-
mkdir project
-
-
进入项目目录,初始化项目目录
-
cd project npm init
-
初始化完成后在当前目录中会生成一个package.json文件,该文件指定项目所以依赖的模块
-
-
配置package.json文件
-
{ "name": "project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "babel-core": "^6.22.1", "babel-loader": "^7.1.1", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "babel-register": "^6.22.0", "css-loader": "^0.28.11", "element-ui": "^2.7.2", "file-loader": "^1.1.4", "lodash": "^4.17.4", "style-loader": "^0.23.1", "url-loader": "^1.1.2", "vue": "^2.6.10", "vue-loader": "^15.7.0", "vue-router": "^3.0.2", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^4.29.6", "webpack-cli": "^3.3.0", "webpack-dev-server": "^3.2.1" } }
-
g该文件定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install 命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。
-
-
安装项目依赖模块
-
npm install
-
-
创建项目文件 main.js ,index.html, App.vue
-
touch index.html main.js App.vue. 可以借助vscode编辑工具创建文件
-
index.html文件时项目的首页文件
-
main.js 文件定义vue及调用单文件组件,也是项目打包时所依赖的文件
-
App.vue文件为单文件组件文件
-
-
创建webpacke打包的配置文件webpack.config.js
-
const path = require('path') const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { entry: { main: "./main.js" }, //入口文件 output: { filename: 'index.js', //出口文件名 path: path.resolve(__dirname), //当前目录 library: 'index' // 打包后模块的名称 }, plugins: [ // make sure to include the plugin for the magic new VueLoaderPlugin() ], module: { rules: [ //定义不同类型的文件使用的loader { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.js$/, loader: 'babel-loader' }, { test: /\.css$/, loader: 'vue-style-loader', }, { test: /\.css$/, loader: 'css-loader', options: { minimize: true //添加 } }, { test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file-loader' }, ] } }
-
在通过webpack对项目进行打包时,需要指定相应的配置文件,同过配置文件对单文件组件中的各个内容进行解析,生成一个index.js的压缩文件,在index.html只需引该文件就可进行页面加载渲染
-
单文件组件的使用
项目搭建完成后需要分别对 main.js , index.html , App.vue 文件进行编写代码
index.html
<!DOCTYPE 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>Document</title>
</head>
<body>
<div id='app'><App></App></div>
<!-- 引入打包后的index.js文件。该文件的名字不是固定名字,可以在webpack.config.js的出口文件中指定 -->
<script src="./index.js"></script>
</body>
</html>
main.js
// 引入vue和App组件
import Vue from 'vue'
import App from './App.vue'
new Vue({
el:'#app',
// 渲染App组件中的内容,返回给index.html文件使用
render:function(creater){
return creater(App)
}
})
App.vue
<template>
<!-- 指定html显示内容 -->
<div>单文件组件</div>
</template>
<script>
// 指定js内容
// export default {
// }
</script>
<style>
/* 指定css内容 */
</style>
项目打包
文件编写完成后并不能直接运行index.html产生效果,需要对项目进行打包生成一个渲染后的index.js文件进行使用
npm run build
打包后会在当前目录下生成一个index.js 文件,在index.html中引用该文件,运行index.html文件看到效果
项目调试运行
每次我们需要看到组件效果需要手动生成一个index.js文件,这是我们可以借助webpack-dev-server自动运行我们的代码
// 在项目目录下,执行下面指令可以开启前端服务,自动运行前端代码
./node_modules/.bin/webpack-dev-server
多个单文件组件使用
在project目录下创建components文件夹,然后将所有子组件放入components文件夹下
1、多组件嵌套使用
Child1.vue
<template>
<div>子组件1</div>
</template>
<script>
// export default {
// }
</script>
<style>
</style>
Child2.vue
<template>
<div>子组件2</div>
</template>
<script>
// export default {
// }
</script>
<style>
</style>
App.vue
<template>
<div>
单文件组件
<!-- 调用子组件 -->
<Child1></Child1>
<Child2></Child2>
</div>
</template>
<script>
//导入components目录下的子文件 Child1为指定的组件名,可以任意命名,不一定按照文件名
import Child1 from './components/Child1.vue'
import Child2 from './components/Child2.vue'
export default {
// 将子组件添加到App.vue中
components:{
Child1,
Child2,
}
}
</script>
<style>
</style>
2、多组件路由使用
使用路由形式将多个单文件组件组合在一起
-
定义路由目录和路由文件
mkdir router touch router.js
-
编写路由文件router.js
-
import Vue from 'vue' // 导入路由插件 import Router from 'vue-router' import Child1 from '../components/Child1.vue' import Child2 from '../components/Child2.vue' // 在vue中使用插件 Vue.use(Router) export default new Router({ // 定义匹配规则 routes:[ { path:'/', // 匹配根路径/,加载Chiled1中的内容 component:Child1 }, { path:'/child2', component:Child2 } ] })
-
-
在main.js中使用路由
-
import Vue from 'vue' import App from './App.vue' //导入定义好的路由 import router from './router/router.js' new Vue({ el:'#app', router, //使用路由 render:function(creater){ return creater(App) } })
-
-
在App.vue中指定路由标签
-
<template> <div> 单文件组件 <!-- 记载路由标签 --> <router-view></router-view> </div> </template> <script> </script> <style> </style>
-
Element-ui
单文件组件就像是一个个封装好的页面样板,我们可一把这些样板组合在一起形成一个完整的页面。就像QQ空间装扮一样,将个个样板放入QQ空间页面中组成自己风格的页面。而Element-ui就将我们需要的样式封装成单文件组件,我们可以直接集成到我们的项目中。
-
在main.js中将emelent-ui引入到项目中
-
import Vue from 'vue' import App from './App.vue' import router from './router/router.js' // 引入ElementUI import ElementUI from 'element-ui' // 引入css import 'element-ui/lib/theme-chalk/index.css' // 使用ElementUI Vue.use(ElementUI) new Vue({ el:'#app', router, render:function(creater){ return creater(App) } })
-
-
在子组件中使用element-ui的代码,
-
<template> <div> <div class="block"> <span class="demonstration">默认</span> <el-slider v-model="value1"></el-slider> </div> <div class="block"> <span class="demonstration">自定义初始值</span> <el-slider v-model="value2"></el-slider> </div> <div class="block"> <span class="demonstration">隐藏 Tooltip</span> <el-slider v-model="value3" :show-tooltip="false"></el-slider> </div> <div class="block"> <span class="demonstration">格式化 Tooltip</span> <el-slider v-model="value4" :format-tooltip="formatTooltip"></el-slider> </div> <div class="block"> <span class="demonstration">禁用</span> <el-slider v-model="value5" disabled></el-slider> </div> </div> </template> <script> export default { data() { return { value1: 0, value2: 50, value3: 36, value4: 48, value5: 42 } }, methods: { formatTooltip(val) { return val / 100; } } } </script>
-
Vue-cli的使用
我们的项目文件都是手动创建出来,在实际开发中我们可以借助vue-cli创建出我们的所有项目文件
-
全局安装vue-cli
-
npm install --global vue-cli
-
-
项目创建
-
vue init webpack 项目名
-
-
运行调试项目
-
// 进入项目目录下,执行下面指令 npm run dev
-
-
项目打包
-
npm run build
-
项目目录结构
- 文件夹1(src),主开发目录,要开发的单文件组件全部在这个目录下
- 文件夹2(static),静态资源目录,所有的css,js文件放在这个文件夹
- 文件夹3(components),组件目录,vue格式的单文件组件都存在这个目录中
- 文件夹4(router),路由目录,在此文件夹中配置组件路由
还有node_modules目录是node的包目录,config是配置目录,build是项目打包时依赖的目录。