VUE简介
Vue是一套用于构建用户界面的渐进式框架。
在设计上使用MVVM(Model-View-View-Model)模式。MVVM由MVC衍生。
View和ViewModel之间通过双向绑定(data-binding)建立联系。
MVVM的组成:
图片来源:前后端分手大师——MVVM 模式
VUE的强大
Vue.js通过MVVM模式拆分为视图与数据两部分,并将其分离。因此,你只需关心数据部分,DOM的事情Vue会帮你搞定。
因此Vue可以应对更复杂的业务场景:SPA,组件解耦等。
Vue的使用
1.创建Vue实例
通过构造函数Vue创建一个Vue的根实例。
new Vue({})
- 挂载点:Vue实例操作的DOM的元素。
- 模板:挂载点的内容。可以写在元素内,也可以写在template属性下。
2.实例的参数
传入一个参数:是一个大的字面量对象。
- el:
绑定Vue实例与DOM。
创建一个实例后,让实例去接管挂载点里面的内容。指定一个页面中已存在的DOM元素来挂载Vue实例。可以是HTMLElement,也可以是CSS选择器。挂载成功后使用app.$el来访问该元素。 - data:实例的数据项。是一个字面量对象。
- template:模板内容。
- methods:事件触发的方法集。
- computed:计算属性。通过前置值计算得来,如果计算值没有变化,将会使用上一次计算的缓存值。
- watch:侦听器。侦听某一个数据项的变化,一旦数据变化,就可以执行业务逻辑。
<div id="app">
<div>{{msg}}</div>
</div>
<script>
new Vue({
el:"#app",
data:{
msg:"hello"
}
template:'<div>{{msg}}</div>' // 写出仅为展示方便
})
</script>
// 3 数据,事件和方法
<div id="root">
//<h1>hello {{msg}}</h1>
//<div v-text="content"></div>
//<div v-html="content"></div>
<div @click="handleClick">{{content}</div>
</div>
<script>
new Vue({
el:"#root",
data:{ // data数据项如何显示在模板上
msg:"world"
content:"hello"
}
method:{
handleClick:function(){
this.content="world"
}
}
})
</script>
// 4 属性绑定和双向数据绑定
<div id="root">
// <div title="title">hello world</div> 此时title的值是字符串"title"
<div :title=" 'roc' + title">hello world</div> // 此时实现属性绑定,属性值不再是单纯的字符串,而是JS表达式
--------------------------------属性绑定-------------------------------------
<input v-model="content"/> // 双向绑定
<div>{{content}}</div>
</div>
<script>
new Vue({
el:"#root", // 通过单项绑定,<div>的内容由数据项content决定
data:{
title:"this is hello world",
content:"this is content"
}
})
</script>
// 5 计算属性和侦听器
<div id="root">
姓:<input v-model="firstName"/>
名:<input v-model="lastName"/>
<div>{{firstName}}{{lastName}}</div>
<div>{{fullName}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:'',
lastName:'',
count:0
}
computed:{
fullName:function(){
return this.firstName + '' + this.lastName
}
},
watch:{
fullName:fucntion(){
this.count ++
}
}
})
</script>
// 6 v-if 、 v-show 、 v-for
<div id="app">
<div v-if="show">hello world</div>
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for="item of list" :key="item">{{item}}</li>
<li v-for="(item, index) of list" :key="index">{{item}}</li> // :key用于提升性能,值不能相同,相同时使用这种写法:item为循环内容,index为循环序号
</ul>
</div>
<script>
new Vue({
el:"#app",
data:{
show:true,
list:[1,2,3]
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
})
</script>
{{}}是插值表达式。
改变数据的显示不用改变DOM,改变数据即可。面向数据编程。
通过引入模板指令,属性值的部分就不再是一个字符串了,而是一个JS表达式。
3.指令
- [ v-text = 数据项中的属性变量 ] —
模板内容
:元素的内容由v-text对应的变量决定,会转义
,输出纯文本 - [ v-html = “value” ] —
模板内容
:元素的内容由v-html对应的变量决定,不会转义
- [ v-on:event=”function” ] —
事件绑定
—简写:[ @event="fucntion" ]
- [ v-bind:attr=”value” ] —
属性绑定
:attr属性和value数据项绑定 —简写:[ :attr="value" ]
- [ v-model = “value”] —
双向绑定
:当前DOM元素与数据项会互相影响 - [ v-if = “value(boolean)” ] — 控制元素存在:创建和去除
- [ v-show = “value(boolean)” ] — 控制元素显示:display属性
- [ v-for = “value” ] — 控制一组数据循环
4.组件
组件就是自定义一个具有一定逻辑功能的标签,里面携带着相应的结构(template)和功能(methods)。
根实例也是根组件,由众多子组件构成,子组件本身也是一个子实例。
创建一个组件:
// 全局组件
Vue.component('组件名称', {组件内容})
<todo_item></todo_item>
Vue.component('todo_item',{
props: ['content','index'], // 组件接收从外部传入的参数
template: '<li @click="handleClick">{{content}}</li>', // 组件的模板
methods:{ // 组件的方法集
handleClick:function(){
this.$emit('delete',this.index) // 发布订阅模式
},
}
})
// 局部组件
<todo_item></todo_item>
var Todo_Item = {
template:''
} // 声名组件内容包
new Vue({
el:'#root',
component:{ // 注册组件,组件名称与组件内容绑定
'todo_item':Todo_Item
}
})
组件通信
- 父级与子级通信通过为子组件添加属性。
- 子级与父级通信通过发布订阅模式。
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item" //-------------------
:index="index" //-------------------
@delete="handleDelete" //-----------------父级订阅
>
</todo-item>
Vue.component('todo-item', {
props: ['content','index'], //--------------------- 组件注册接收从外部传入的参数
template: '<li @click="handleClick">{{content}}</li>',
methods:{
handleClick:function(){
this.$emit('delete',this.index) //---------------- 发布订阅模式
},
}
})
5 使用Vue创建TodoList应用
<body>
<div id="root">
<div>
<input v-model="inputValue">
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index" :content="item"
:index="index"
@delete="handleDelete"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item', {
props: ['content', 'index'],
template: '<li @click="handleClick">{{content}}</li>',
methods: {
handleClick: function () {
this.$emit('delete', this.index)
},
}
})
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function () {
this.list.push(this.inputValue);
this.inputValue = ''
},
handleDelete: function (index) {
this.list.splice(index, 1)
}
}
})
</script>
</body>
Vue-cli脚手架
项目框架自动构建
vue init webpack <project_name>
cd <project_name>
npm run dev
通过Vue-cli体验工程化项目流程:
// main.js
import Vue from 'vue'
import TodoList from './TodoList.vue'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { TodoList },
template: '<TodoList/>'
})
// TodoList.vue
<template>
<div><!-- vue语法要求模板内的标签被一个容器包裹 -->
<div id="app">
<input v-model="inputValue"> <!-- 数据项与元素双向绑定-->
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
:index="index"
@delete="handleDelete"
> <!--父组件在自己的地盘通过向子组件添加属性进行通信-->
<!--:content指的就是item不再是简单的字符串,而是一个表达式,一个对应值的变量-->
</todo-item>
</ul>
</div>
</template>
<script>
import TodoItem from './components/TodoItem.vue'
export default {
components: {
'todo-item': TodoItem
},
data () { // ES6简化函数写法
return {
inputValue: '',
list: []
}
}, // 在vue-cli中的组件data不再是一个对象,而是一个函数
methods: {
handleSubmit () { // ES6简化函数写法
this.list.push(this.inputValue)// this指向本实例,相当于this.$data.list
this.inputValue = ''
},
handleDelete (index) { // 参数别忘传
this.list.splice(index, 1)
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
// TodoItem.vue
<template>
<li class="item" @click="handleDelete">{{content}}</li> <!--父级工作完毕,子级注册完毕,从工具包中寻找可以使用的变量,进而插入元素中-->
</template>
<script>
export default{
props: ['content', 'index'], // 注册父级传入的参数
methods: {
handleDelete () {
this.$emit('delete', this.index)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> /* 添加作用域,成为局部样式 */
.item {
color:green;
}
</style>
Bug汇总
vue2.0(新手)第一个坑–do not mount Vue to !!!
使用vue-cli脚手架搭建项目,保存编译时出现的代码检查错误(ESLint)
- 第一步 node环境安装
- 第二步 node环境检测
node -v
npm -v - 第三步 vue-cli脚手架安装
- 安装vue-cli
npm install vue-cli -g - 初始化项目
vue init webpack vue-demo - 进入 cd vue-demo
- 执行 npm install
- 接下来执行 npm run dev
- 安装vue-cli
常用指令
npm run dev 执行脚本
ctrl+c 退出 npm run dev
Vue-cli脚手架搭建 — build / dev-server消失
自Vue-cli升级到2.9.1以后,在build文件夹下的dev-server.js就没有了。
解决方案:Vue2.0史上最全入坑教程(续)—dev-server失踪问题解答
Vue-cli脚手架搭建 — ESlint问题
使用vue-cli脚手架构建了webpack项目,在开发过程中,Eslint验证十分严谨,可以改变设置。
解决方案:使用vue-cli脚手架搭建项目,保存编译时出现的代码检查错误(ESLint)
数据mock
Web应用前后端(台)分离:
后台向前台提供API接口,只负责数据的提供和计算,而完全不处理展现;
前台通过Http(Ajax)请求获取数据, 在浏览器端动态构建界面显示数据。
Google插件
JSONView — 在谷歌浏览器中查看json格式化数据
谷歌浏览器中安装JsonView扩展程序