推荐一个网站,该网站详细的介绍了vue的所有内容:http://doc.liangxinghua.com/vue-family/1.3.html#
Vue是一套用于构建用户界面的渐进式框架,与其他框架不同的是,Vue被设计为可以自底向上逐层应用,Vue的核心库只关心视图层,为复杂的单页应用提供驱动,只支持IE8 以上的浏览器使用。
Vue 引入js库:
<script src="node_modules/vue/dist/vue.min.js"></script>
Vue的实例创建
var vue = new Vue({});
在创建Vue实例的时候,里面的属性有 el (用于绑定Vue实例的)、data(用于显示数据的,在页面中显示文本属性都必须在data中声明,如果不声明就使用Vue去管理,会报没有定义的错误)、methods(用于定义函数,所有的函数都定义在改属性中)
var todos = [{id: 1, title: "123"}, {id: 2, title: "456"},{id: 3,title: "789"}];
var vue = new Vue({
el: "#app",
data: {
foo: "hello",
bar: "world",
todos: todos,
strHtml: "<h1>asd</h1>",
once: "qwe"
}
});
Vue的标签:
{{ }} : 用于操作文件,取值 , 可以取在data中的数据,或者是遍历出来的数据
<p> {{ firstname + listname }} </p>
v-bind: 用于操作属性,简写方式 :
<input type="checkbox" v-bind:id="item.id" value="Jack" v-model="item.done">
v-bind:style 用于操作样式 : 内联样式。可以用于直接实例对象的属性
直接将样式写死 , 表示下面的颜色就是 red
<h :style="{backgroundColor:'red'}">nihao</h>
颜色的值是可取的,但是需要在data中进行定义,但是不要使用单引号括起来使用
<h :style="{backgroundColor: bac}">nihao</h>
bac需要在 data中定义,并且赋值,然后在该 { } 括号中直接使用
v-class : 用于操作样式的 , 在操作样式的时候,如果后面返回的false 则表示该样式不生效
<h1 :class="{active :false}">hello word</h1>
v-model : 用于进行数据的双向绑定,在操作的时候,会直接操作data中的具体的数据,包括vue中数据的数据
名字:<input type="text" value="国庆" v-model="listname">
<script>
new Vue({
el: "#app",
data: {
firstname: "",
listname: ""
}});
</script>
v-on : 用于进行绑定事件,比如绑定点击事件(v-on:click),简写的方式@click
<button @click="delect(index)">x</button>
@click.prevent : 该事件用于阻止浏览器的默认事件,简写方式
<a @click.prevent="" href="http://www.baidu.com">去百度</a> 在跳转的时候,会浏览器会阻止
原始的方法需要调用 preventDefault() 方法
new Vue({
el: "#app",
data: {},
methods: {
goToBaidu: function (e) {
// 该方法用于阻止默认的事件
e.preventDefault()
}
}
});
v-html: 用于将数据按照html的格式进行数据的解析
var vue = new Vue({
el: "#app",
data: {
foo: "hello",
bar: "world",
todos: todos,
strHtml: "<h1>asd</h1>",
once: "qwe"
}});
<ul>
<li v-html="strHtml">{{ strHtml }}</li>
</ul>
v-once:用于将该数据表示为类似于final的数据类型,只能赋值一次
<ul>
<li v-once="once">{{ once }}</li>
</ul>
Templare 标签
在使用该标签的时候,是不会在Dom中添加并显示的,该标签是Vue特定的标签,使用的场景,当有多个标签有同样的样式或者功能的时候,就使用该标签将多个标签放在该标签中,并在该标签上进行属性的操作或者条件判断,下面使用的场景适用于判断
<template v-if="toda.length">
<section class="main">
<input id="toggle-all" @change="checkedDown" class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<!-- These are here just to show the structure of the list items -->
<!-- List items should get the class `editing` when editing and `completed` when marked as completed -->
<!--
使用的时候注意:需要使用双向绑定来进行数据的绑定,从而在点击的时候改变双向绑定的值,从而来控制样式的变化
-->
<li v-for="(item,index) in toda"
:class="{
completed:item.comleted,
editing:item == updateDataItem
}">
<div class="view">
<input class="toggle" type="checkbox" checked
v-model="item.comleted">
<label @click="updateData(item)">{{item.title}}</label>
<button class="destroy" @click="deleteButton(index,$event)"></button>
</div>
<input class="edit"
@keydown.enter="keydownUpdata(index,$event)"
@blur="handleSavaEditKeyDown(item,index,$event)"
@keydown.esc ="handleCancelEditEsc"
v-model="item.title">
</li>
</ul>
</section>
</template>
页面刷新文本框获得焦点
在普通的html页面,使用获取输入框的焦点,在input标签上添加autofocus属性,在页面刷新的时候就会获得焦点,可是上面的额用法是原生的,当在使用Vue去管理当前输入框的时候,autoFocus,就会失去作用,此时需要使用到Vue中的标签去管理
v-focus : 是Vue中的用于让单钱标签获取焦点,但是在使用的时候需要引入该标签的自定义用法
Directive : 用于设置自定义标签的
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
});
自定义标签:(在使用自定义标签的时候一定是要操作底层Dom的)
自定义标签的作用是可以直接操作底层的Dom元素,因为封装的标签不可能操作底层的,所以在使用的时候,需要将底层的操作封装起来使用。
创建自定义标签的方法就是上面的directive方法,在创建标签的时候,会涉及到几个方法,下面进行说明:
Bind : 用于初始化数据的,但是在该节点中是获取不到父节点的数据的
Inserted : 用于初始化数据的,是可以获取到父节点的数据的,跟Bind 的用法是一致的,区别就在于该方法是可以获取到父节点元素,Bind 是不可以获取父节点的元素的。
Update : 当自定义元素在模板中的元素发生改变(当模板中的元素发生改变的时候,当前元素所在的模板也会发生改变的时候),才会调用该方法和下面的方法。
ComponentUpdate : 跟上面的Update同时调用,该方法获取的是元素修改之后的数据,而Update获取的修改之前的数据
Unbind : 该方法是档案元素跟Dom解绑的时候调用,就是当 当前模板消失的时候,比如隐藏,的时候l
例如,在一个div中有一个定时器,用于定时打印数据,而当该div消失或者隐藏的时候,此时div中的定时器也没有存在的价值,所以就会调用该方法,而我们所做的操作就是删除该定时器
/*
* 在使用自定义标签的,操作的对象是: 当 模板 发生 改变的时候,才会触发, 所谓的模板。指的是:
* 块级元素或者是行内块元素,指的就是包含 数据 的 标签,当数据发生改变的时候,此时的模板(就是包含数据的标签)会发生变化,此时就会触发自定义标签
* */
Vue.directive("demo", {
// bind 和 inserted 方法,会在初始化的时候,执行,并且只会执行一次
// 获取父类节点,用于获取父节点,但是在获取的时候,父节点并获取不到
bind(el, binding){
console.log("bind", el.parentNode);
},
// 可以获取父节点,元素,跟bind的作用是一样的,只不过bind不能获取父节点
inserted(el, binding){
el.itemInterval = setInterval(function () {
console.log("Hello");
}, 1000);
console.log("inserted", el.parentNode);
},
// 用于修改后的数据,当bind 和 inserted 中的数据修改之后,update 才会被调用,如果数据不修改的话,该方法是不会被调用的,调用的数据 是修改之前的数据
update(el, binding){
console.log("updated", el.innerHTML);
},
// 当bind 和 inserted中的数据被修改之后,才会调用该方法,该方法跟上面的 update 的调用的是一起的,但是获取的是 修改之后的数据
componentUpdated(el, binding){
console.log("componentUpdated", el.innerHTML);
},
// 用于解除 Dom 和 元素 的关系 , 当在当前元素中添加了特备的事件的时候,当该显示的元素消失的时候,需要将该元素在该方法中消除掉
unbind(el, binding){
console.log("unbind");
console.log(el);
window.clearInterval(el.itemInterval);
}
});
解决表达式闪烁的问题:
出现闪烁的问题是: 在数据加载的时候会出现数据渲染的情况
v-text : 直接在标签上面进行数据的绑定
<h1 v-text="message"></h1>
v-cloak : 在style中进行设置
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app" v-cloak>
<h1 v-text="message"></h1>
</div>
会在Vue 解析处理完模板之后就会自动把作用在v-cloak 上面的上面的样式display: none;改变成display: block;
就是先将该数据隐藏,当数据加载完成自后,再进行数据的显示。
v-if和v-show的区别
两者的区别:
v-if 表示的是:如果当前的数据是真的,才会对数据进行渲染,如果不是真的就不会对数据进行渲染
v-show: 表示的是,无论条件是否为真都会进行渲染,但是在显示的时候会根据条件判断是否要显示
<div v-if="seen" style="border: 1px solid red; width: 300px; height: 300px"></div>
<hr/>
<input type="checkbox" :checked="seen">
<div v-show="seen" style="border: 1px solid red; width: 300px; height: 300px"></div>
v-pre:
<span v-pre>{{ this will not be compiled }}</span>
被修饰的标签中的内容是不会被Vue解析的,因为会告诉Vue,该标签中不会存在需要Vue去解析的数据或者标签
计算属性:(computed)
该computed标识用于计算属性,在使用的时候,里面的是方法的形式,但并不是在methods中使用,并不能当成方法去使用,只能做属性去使用,在属性中会有get和set两个方法,get方法在使用该属性名称的时候,会被调用,set是在设置值的时候,会被调用,最重要的一点是就是,该计算属性是用于当多个地方用到同一个数据的时候,如果当前的属性被计算出来,会被缓存起来,当下次调用的时候,直接从缓存中获取即可。
// computed 该对象是用于设置,计算属性的,虽然里面设置的是方法,但是不能
//当 methods来使用,里面是设置计算实行的方法,在调用的时候,直接写方法名称即可
// 不用像函数那样添加括号
computed: {
//下面这种方式是简写的方式
// remaningCount:function () {
// return toda.filter(t => !t.comleted).length
// }
//完整的写法
//在计算属性的对象中,有get和set的方法,在调用的时候会默认调用git方法 ,如果想设置值,remaningCount = XXX
remaningCount: {
get(){
return this.toda.filter(t => !t.comleted).length
},
set(){
console.log("...");
}
}
监视(watch)
作用,用于监视数据的,当监视的数据发生改变的时候,才会调用该监视中的方法,监视的数据是在data中定义的
象监听到
watch:{
// 作用是用于监听toda 数据,当该数据发生改变的时候,就会被监听到,
// 但是在使用的时候,如果你需要监听的不是简单的数据类型,是对象类型的需要添加 deep: true 用于表示 开启深层次的数据解析
// 开启更深层次的监听, 如果只是监听基本数据类型的数据,不需要使用该标签,
toda: {
// 方法,刷新的要进行的操作,,
// 用法,当数据发生改变的时候,就重新将数据放到localStorage ,从而完成数据的更新 val: 更新的数据、oldVal:更新之前的数据
handler: function (val, oldVal) {
console.log("数据被改变");
window.localStorage.setItem("todaData",JSON.stringify(this.toda));
},
// 该注解的意思是用于,实时刷新,如果不开启,只有当数据发生改变的时候,才会触发该函数,而使用
// immediate: true 的意思就是 实时的刷新
deep:true,// 用于解析对象属性的数据
immediate: true
}
}
组件:(可复用的Vue实例)Componet ,在使用组件的时候需要注意,如果组件名称是按照驼峰命名的,在使用的时候每个大写字母之间使用 - 分隔
component : 用于自定义组件。
// 全局注册组件,可以用在其被注册之后的任何新创建的Vue跟实例中,也包括其树中的其他子组件
Vue.component("button-counter", {
// 在使用的时候,Data 提供的是一个对象,需要将数据返回
// 这样做的目的是,在使用的时候,每次使用自定义组件的时候,都会创建一个新的对象,保证数据的唯一性
// 如果不保证数据的唯一性,会导致其他实例会受到一个实例点击的影响,每一个组件中的数据,在别的组件中是不能获取并使用的
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count ++">You clicked me {{ count }} tiems.</button>'
});
new Vue({
el: "#components-demo"
});
注意: 在使用的时候,自定义组件中的data 数据是一个方法,在该方法中返回的是一个对象,在该data中定义的变量,在template中可以直接使用。
在使用组件的时候,分为局部组件和全局组件,全局组件在定义完成之后,其后面的组件可以直接使用,
全局组件定义的方式
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
局部组件定义的方式:在Vue实例中使用components属性创建的。局部组件在其他组件中是不能被访问的
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
父子间通信:
父组件传递消息给子组件,使用 props 。子组件向父组件传递消息,使用 emit。
单向数据流,在使用的时候,父类中传递给子类的对象,子类是不能修改其内存的指向的,可以进行修改,在操作的时候只要不修改其变量在内存中的指向即可,但是不建议使用该方式去修改值,因为在修改完成之后,父类中传递的对象数据并不知道由那个子类去修改的。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
在使用props的时候,可以对传递的数据进行验证,但是在使用验证的时候,不是将props定义为一个数组,而是定义为一个对象进行数据的校验,在使用基本数据类型的时候,也还可以使用对象类型
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 匹配任何类型)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
使用对象的方式进行校验
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
Vue.component('blog-post', {
props: {
author: Person
}
})
$emit: 表示子类数据传递给父类组件
this.$emit('todoTodos',value);
参数一:表示当前子类传递给父类的事件,参数二:表示的是传递的值
<todo-todos @todoTodos="todos"></todo-todos>
Vue.component('todo-todos',{
methods:{
todos:function(){
}
}
});
说明,在子类的标签中(组件),$emit 的方法的事件的名称 todoTodos ,必须要添加相同名称的时间,该事件对应下面组件中的方法
Vue的生命周期:
beforeCreate : 是在解析Vue实例的时候调用的,但是此时的data 和 methods 中是没有数据的,是获取不到在页面要显示的数据,
Create : 是在Vue中的数据解析完成,数据在methods 和 data中可以获取到,但是此时的数据只是在内存中
beforMount : 表示的数据在内存中完成模板解析,但是此时的数据并没有渲染到页面
Mounted : 此时的数据已经在页面中显示,但是数据html模板已经渲染完成,该方法结束之后,就会在页面显示
beforeUpdate : 方法是在数据发生改变的时候调用,只有页面的参数发生改变该方法才会调用,但是此时的数据是存在于内存中,并不没有在页面中显示,页面显示的还是之前的老的数据
Virtual DOM re-render and patch : 表示会将最新的数据渲染到页面,
update : 此时页面显示的数据是最新的,内存中的数据已经渲染到页面中
destroyed : 此时处于销毁阶段,所有的数据(data、methods。。。)会全部销毁
vue-resource: 用于请求的第三方插件,用于模仿jquery的请求(get、post、jsonp),设置请求的路径
<div id="app">
<input type="button" value="get请求" @click="getInfo">
<input type="button" value="post请求" @click="postInfo">
<input type="button" value="jsonp请求" @click="jsonpInfo">
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-resource/dist/vue-resource.js"></script>
<script>
/*
* 设置全局的请求路径
* */
Vue.http.options.root = 'http://www.baidu.com';
//在使用post 的时候,需要设置数据发送的格式
Vue.http.options.emulateJSON = true;
new Vue({
el: "#app",
data: {},
methods: {
getInfo() {
this.$http.get("").then(function (resout) { });
},
postInfo() {
// 参数二:表示的是请求的数据
// 参数三: 表示的是发送数据的格式
this.$http.post("", {}, {}).then(function () { });
},
jsonpInfo() {
this.$http.jsonp("").then(function () { });
}
}
});
动画过渡:Vue设置的动画还是蛮有意思的
在看官网的时候,官网中提示可以使用第三方插件进行使用,这边小编使用的是animate.css,感觉还是不错的
animate.css 的网址:https://daneden.github.io/animate.css/
引入:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">
在设置的时候,设置的是动画的过程,是在插入元素的时候,执行的动画效果
<div id="app">
<input type="button" value="显示" @click="show = !show">
<transition
enter-active-class="animated rotateIn"
leave-active-class="animated rotateInUpLeft"
>
<h1 v-if="show">显示数据</h1>
</transition>
</div>
<script>
new Vue({
el: "#app",
data: {
show: false
}
});
</script>
使用javascript钩子来完成动画效果
网址:https://cn.vuejs.org/v2/guide/transitions.html#JavaScript-%E9%92%A9%E5%AD%90
在使用的时候,需要注意在enter的时候,一定要调用 done方法,否则动画达不到预期的效果
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<!--add by shanggq 2019/1/30 start-->
<meta charset="UTF-8">
<title>小球</title>
<script src="node_modules/vue/dist/vue.js"></script>
<link rel="stylesheet" href="node_modules/animate.css/animate.css"/>
</head>
<style>
.bail {
width: 30px;
height: 30px;
background: red;
-moz-border-radius: 60px;
-webkit-border-radius: 60px;
border-radius: 60px;
}
</style>
<body>
<div id="app">
<input type="button" v-on:click="show = !show " value="显示"/>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
>
<p v-if="show" class="bail"></p>
</transition>
</div>
<script>
new Vue({
el: "#app",
data: {
show: false
},
methods: {
beforeEnter(el) {
el.style.transform = "translate(0,0)";
},
enter(el, done) {
// 返回元素的宽度(包括元素宽度、内边距和边框,不包括外边距)
el.offsetWidth;
el.style.transform = "translate(150px,100px)";
el.style.transition = "all 3s ease";
done();
},
afterEnter() {
this.show = !this.show;
}
}
});
</script>
</body>
</html>
<!--add by shanggq 2019/1/30 end-->
上面是一个小的案例,可以阅读一下,不明白的可以下方留言
对于列表渲染,for循环渲染出来的数据,需要使用transition-group 的标签才可以使用,如果使用transition是不能生效的
<transition-group appear
tag="ul">
<li class="bail" v-for="(item,index) in srt" :key="item.id" @click="del(index)">
<td>"姓名:"+{{item.name}}+"-- 年龄"+{{item.age}}</td>
</li>
</transition-group>
在使用的时候,需要设置key ,如果不设置在渲染的时候,会报错,设置key还有另一个用途,就是在复选框勾选一个元素,然后再添加一个元素的时候,勾选的状态是不会发生改变的,
其中
appear :是用于设置,当页面在一开始加载的时候,就会执行动画效果,
tag:适用于替换标签的,因为在循环遍历显示数据的时候,在最li 标签的外面包含的是span标签,所以使用tag属性设置外面要显示的标签
使用Vue自带的动画过渡:
v-enter : 表示元素被添加到指定的位置,在指定的位置前显示的时候,就会执行该动画效果
v-enter-active : 表示在元素添加到指定的位置的时候,执行的动画效果
v-enter-to: 表示在元素元素添加到指定的位置之后,执行的效果,跟v-enter 的效果似乎是相似的
还有三个离开的时候执行的动画效果
v-leave v-leave-active v-leave-to
component标签的使用:
使用的场景,当触发不同的事件,在一个标签中显示不同的效果
<a href="javascript:void(0)" @click.prevent="counName= 'login'"> 登录</a>
<a href="javascript:void(0)" @click.prevent="counName= 'register'">注册</a>
<transition mode="out-in">
<component :is="counName"></component>
</transition>
mode 的效果是用于设置在显示的时候顺序。
路由:
在使用路由的时候使用的是: vue-router 在使用的时候,需要引入该js文件
使用 new VueRouter 来创建理由对象,当引入js文件之后,在页面访问的时候会出现 # 的符号,用来分隔目录
在显示的地方需要添加<router-view></router-view> 标签用于显示自己渲染的模板,但是想多个<router-view></router-view>分别显示不同的数据,需要分别给与name属性,在 components 中分别对应 完成显示
在使用路由的时候,可以设置嵌套路由,父路径下面还有子路由(在父模块中显示子模块) children,在父路径请求下,再显示子路径的请求。
但是在设置的时候,需要在父组件中 添加 <router-view></router-view> 标签,进行显示子路由的数据
使用webpack管理vue 项目:https://blog.csdn.net/weixin_38297879/article/details/87252758
在webpack 的介绍中已经介绍了一些整合vue 一些常规的使用
Vuex 的介绍
Vuex 是一个专为vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,用于管理共享的数据
首先下载 vuex 的插件
cnpm i vuex -S
导入vuex
import Vuex from 'vuex'
注册vuex到vue中
Vue.use(Vuex)
new Vuex.Store() 实例,得到一个 数据仓储对象
var store = new Vuex.Store({
state: {
// 大家可以把 state 想象成 组件中的 data ,专门用来存储数据的
// 如果在 组件中,想要访问,store 中的数据,只能通过 this.$store.state.*** 来访问
count: 0
},
mutations: {
// 注意: 如果要操作 store 中的 state 值,只能通过 调用 mutations 提供的方法,才能操作对应的数据,不推荐直接操作 state 中的数据,因为 万一导致了数据的紊乱,不能快速定位到错误的原因,因为,每个组件都可能有操作数据的方法;
increment(state) {
state.count++
},
// 注意: 如果组件想要调用 mutations 中的方法,只能使用 this.$store.commit('方法名')
// 这种 调用 mutations 方法的格式,和 this.$emit('父组件中方法名')
subtract(state, obj) {
// 注意: mutations 的 函数参数列表中,最多支持两个参数,其中,参数1: 是 state 状态; 参数2: 通过 commit 提交过来的参数;
console.log(obj)
state.count -= (obj.c + obj.d)
}
},
getters: {
// 注意:这里的 getters, 只负责 对外提供数据,不负责 修改数据,如果想要修改 state 中的数据,请 去找 mutations
optCount: function (state) {
return '当前最新的count值是:' + state.count
}
// 经过咱们回顾对比,发现 getters 中的方法, 和组件中的过滤器比较类似,因为 过滤器和 getters 都没有修改原数据, 都是把原数据做了一层包装,提供给了 调用者;
// 其次, getters 也和 computed 比较像, 只要 state 中的数据发生变化了,那么,如果 getters 正好也引用了这个数据,那么 就会立即触发 getters 的重新求值;
}
})
// 总结:
// 1. state中的数据,不能直接修改,如果想要修改,必须通过 mutations
// 2. 如果组件想要直接 从 state 上获取数据: 需要 this.$store.state.***
// 3. 如果 组件,想要修改数据,必须使用 mutations 提供的方法,需要通过 this.$store.commit('方法的名称', 唯一的一个参数)
// 4. 如果 store 中 state 上的数据, 在对外提供的时候,需要做一层包装,那么 ,推荐使用 getters, 如果需要使用 getters ,则用 this.$store.getters.***
添加到vue 的实例中
const vm = new Vue({
el: '#app',
render: c => c(App),
store // 5. 将 vuex 创建的 store 挂载到 VM 实例上, 只要挂载到了 vm 上,任何组件都能使用 store 来存取数据
})
$refs 的使用
用于获取当前操作的vue 值