1.基本指令
//文本
v-text,v-cloak
//标签
v-html
//绑定元素
//v-bind: 中可写入合法的js表达式
v-bind: 可简写成 :
//事件绑定
//@click后面可以不带括号,带括号可以传值
v-on: 可简写成 @
//双向绑定
v-model //注:v-model只能运行在表单元素中
//循环
v-for
//隐藏
//注释元素
//如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if
v-if
//display:none
//如果元素涉及到频繁的切换,推荐使用v-show
v-show
2.事件修饰符
//1. .stop阻止事件冒泡
//2. .prevent阻止默认行为如a链接跳转
//3. .capture捕获触发事件,优先触发.capture事件
//实现捕获触发事件的机制,即是给元素添加一个监听器,当元素发生冒泡时,先触发带有该修饰符的元素。
//若有多个该修饰符,则由外而内触发。
//4. .self只有在点击当前元素的时候才生效(阻止冒泡)
//5. .once只触发一次如@click.stop.once 阻止事件冒泡(只触发一次,第二次无效)
3.vue中的样式
// 1.直接传递一个数组,注意:这里的class需要使用 v-bind数据绑定
<h1 :class="['thin','red']">我是一个h1</h1>
// 2.在数组中使用三元表达式
<h1 :class="['thin',flag?'red':'']">我是一个h1</h1>
// 3.数组中嵌套对象
<h1 :class="['thin','red',{'active':flag}]">我是一个h1</h1>
// 4.直接使用对象
<h1 :class="{ red:true,thin:true,italic:false}">我是一个h1</h1>
//2.内联样式中style可以使用数组或对象
<!-- 1.直接在元素上通过:style,书写对象样式 -->
<h1 :style="{color:'red','font-size':'40px'}">这是一个h1</h1>
<!-- 2.将样式对象定义到data中,并直接引用到:style -->
<h2 :style="obj2">这是一个h2</h2>
<script>
var vue = new Vue({
el: '#container',
data: {
obj2: { color: 'red', 'font-size': '20px' },
obj1: { "letter-spacing": "0.5em" }
},
methods: {}
});
</script>
4.v-for
//可以循环数组,对象,数字
// 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果v-for有问题 必须指定唯一的字符串/数字 类型 :key 值
//of输出值,in输出索引
v-for="(val,index) in list" //list可以是方法(return arr)
//v-for会实时更新
5.过滤器
<body>
<div id="container">
<!-- 过滤器后面可以加过滤器 -->
<p>{{msg | msgFormat('可爱') | test }} </p>
</div>
<script src="lib/vue.min.js"></script>
<script>
//定义一个Vue全局的过滤器
//参数:1.msg,2-n.方法里面的参数
Vue.filter('msgFormat', function (msg, dosth) {
return msg.replace(/单纯/g, dosth);
});
Vue.filter('test', function (msg) {
return msg + "===========";
})
</script>
</body>
</html>
6.实例
<!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>
<link rel="stylesheet" href="lib/bootstrap.css">
</head>
<body>
<div id="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class="panel-body form-inline">
<label>
ID:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name">
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add()">
<label>
搜索关键字:
<input type="text" class="font-control" v-model="keywrods">
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctrime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
// 之前,v-for中的数据,都是直接从data上的list中直接渲染过来的 -->
// 现在,我们自定义一个search(),同时把所有关键字,通过传参的形式,传递给了search()
// 在search()内部,通过执行for循环,把所有的符合 搜索关键字的数据,保存到一个新数组中
<tr v-for="item in search(keywrods)" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime | change('yyyy-mm-dd')}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="lib/vue.js"></script>
<script>
Vue.config.devtools = true;
Vue.filter('change', function (msg, pattern) {
let time = new Date(msg);
let y = time.getFullYear();
let m = time.getMonth() + 1;
let d = time.getDate();
if (pattern && pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`;
}
else {
let hh = time.getHours();
let minutes = time.getMinutes();
let seconds = time.getSeconds();
return `${y}-${m}-${d} ${hh}:${minutes}:${seconds}`;
}
});
var vue = new Vue({
el: '#container',
data: {
id: '',
name: '',
keywrods: '', //搜索关键字
list: [
{ id: 1, name: "宝马", ctime: new Date() },
{ id: 2, name: "奔驰", ctime: new Date() },
]
},
methods: {
add: function () {
this.list.push({ id: this.id, name: this.name, ctime: new Date });
this.id = "";
this.name = "";
},
del: function (id) {
this.list.some((val, i) => {
if (val.id === id) {
this.list.splice(i, 1);
return true;
}
})
},
search: function (keywrods) {
var arr = [];
this.list.forEach(element => {
if (element.name.indexOf(keywrods) != -1) {
arr.push(element);
}
});
return arr;
}
}
});
</script>
</body>
</html>
7.私有过滤器
var vm = new Vue({
el: '#app',
data: {
msg: new Date()
},
methods: {
},
//定义私有过滤器两个条件[过滤器名称 和 处理函数]
//过滤器调用的时候,采用的是就近原则,如果过滤器名称一致,优先调用私有过滤器
filters: {
change(msg,fn(msg,patten))
}
})
8.自定义按键修饰符
<input type="text" class="form-control" v-model="name" @keydown.f2="add">
//自定义全局键盘修饰符
//这里将f2的的keyCode换成了enter的keycode,所以按下enter才会触发add()
Vue.config.keyCodes.f2 = 13;
9.自定义全局指令
<input type="text" class="font-control" v-model="keywrods" v-focus>
//使用Vue.directive()定义全局的指令 v-focus
//参数1.指令名称,参数2.对象
Vue.directive('focus',{
bind(el){
//每当指令绑定到元素上的时候,会立即执行这个bind函数,只执行一次
//在元素刚绑定了指令的时候,还没有插入到DOM中去,这时候,调用focus()没有作用
//因为,一个元素只有插入DOM之后,才能获取焦点
},
inserted(el){
//表示元素插入到DOM中,执行inserted函数(执行一次)
el.focus()
},
update(el){
//函数更新执行多次
}
})
10.使用自定义指令钩子函数传递值
<input type="text" class="font-control" v-model="keywrods" v-focus v-color="'green'">
Vue.directive('color', {
bind(el, binding) {
//和样式相关的操作一般在bind()中进行
el.style.color = binding.value;
}
})
11.自定义指令函数的简写
<div id="app">
<p v-fontsize="'50px'">p标签</p>
</div>
var vm = new Vue({
el: '#app',
data: {
msg: new Date()
},
methods: {
},
//指令函数的简写
directives: {
'fontsize': function (el, binding) {
el.style.fontSize = parseInt(binding.value) + 'px';
el.style.color = "green";
}
},
})
12.生命周期函数
var vue = new Vue({
el: '#container',
data: {
msg: "ok",
str:"destroy"
},
methods: {
show() {
console.log("show");
},
destroy() {
this.$destroy();
}
},
beforeCreate() {//第一个生命周期函数,表示实例完全创建出来之前,会执行它
// this.show();
},
created() {//第二个生命周期函数,可以输出实例里面的值
this.show();
},
beforeMount() {//第三个生命周期函数,表示模板在内存中编辑完成了,但尚未把模板渲染到 页面中
let txt = document.getElementsByTagName("p")[0].innerText;
console.log(txt);
},
mounted() {//最后一个生命周期函数,表示内存中的模板已经渲染到页面中了
//当执行完mounted()以后,表示实例已经完全创建好了
console.log(document.getElementsByTagName("p")[0].innerText);
},
beforeUpdate() {
console.log('界面上元素的内容:' + document.getElementsByTagName("p")[0].innerText);
console.log('data中msg的内容:' + this.msg);
//结论:当执行beforeUpdate的时候,页面中的显示的数据还是旧的,此时data数据是最新的,页面尚未和最新的数据保持同步
},
updated() {
console.log('界面上元素的内容:' + document.getElementsByTagName("p")[0].innerText);
console.log('data中msg的内容:' + this.msg);
//update事件执行的时候,页面和data数据已经保持同步了
},
beforeDestroy() {
this.str="";
console.log("1");
},
destroyed() {
console.log(2);
},
});
13.resource
//<script src="lib/vue-resource.js"></script>
async getInfo() {
let body= await this.$http.get("http://api.cms.liulongbin.top/api/getlunbo");
console.log(body);
},
postInfo() {
//发起Post请求 application/x-www-form-urlencoded
//手动发起的Post请求,默认没有表单格式,所以有的服务器处理不了
//通过post方法的第三个参数,{emulateJSON:true}设置 提交的内容类型为 普通表单数据格式
this.$http.post('http://www.liulongbin.top:3005/api/post', {}, { emulateJSON: true }).then((result) => console.log(result.body));
},
jsonpInfo() {
this.$http.jsonp('http://www.liulongbin.top:3005/api/jsonp', {}, { emulateJSON: true }).then((result) => console.log(result.body));
}
}
});
14.axios
// <script src="lib/axios.js"></script>
//注:axios不支持发送jsonp
async getInfo() {
const result = await axios.get("http://api.cms.liulongbin.top/api/getlunbo");
console.log(result);
},
async postInfo() {
const result = await axios.post('http://www.liulongbin.top:3005/api/post', { name: "zs", age: 18 });
console.log(result);
}
15.使用过渡类名
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(100px);
}
.v-enter-active,
.v-leave-active{
transition: all 1s ease;
}
</style>
<body>
<!-- 1.要实现动画的元素,要使用transition元素包裹起来 -->
<!-- 2. 必须使用v-if或者v-show控制-->
<transition>
<h3 v-show="flag">使用过渡类名</h3>
</transition>
<script>
/*
v-enter和v-enterTo:入场之前的状态,入场之后的状态
v-leave和v-leave-to:元素离开之时的状态,元素离开之后的状态
*/
var vue = new Vue({
data: {
flag: false
},
methods: {}
});
</script>
</body>
</html>
16.动画概念
//1.Vue把一个完整的动画,拆分成了两部分:入场动画和出场动画
//2.入场动画中,包含两个时间点,分别是进入之前(v-enter)和进入之后(v-enter-to)
//3.v-enter表示动画入场之前的起始状态,比如:透明度为0,横向偏移量为50px
// 4.v-enter-to表示动画入场完成之后的终止状态,比如:透明度为1,横向偏移量为0px
// 5.v-enter-active表示入场动画的时间段,在这里,可以规定动画的时长,还有一些相关的动画效果ease
17.动画生命周期
<transition @before-enter='beforeEnter' @enter='enter' @after-enter='afterEnter'>
<div id="ball" v-show='flag'></div>
</transition>
<script>
methods:{
//开始之前的动画
beforeEnter(el){
},
//结束之后的动画
enter(el,done){
done()//done就是afterEnter
},
//动画结束之后的函数,用来做一些清理工作
afterEnter(el){
}
}
</script>
18.列表过渡
<style>
.v-move {
/*让元素被改变定位的时候,有一个缓动的效果*/
transition: all 0.8s ease;
}
.v-leave-active {
/*要被删除的那个元素*/
/* 添加position为absolute才有缓动效果 */
position: absolute;
}
</style>
<!-- transition-group标签为v-for提供动画 -->
<transition-group tag="ul">
<!-- 添加ul标签 -->
<li v-for="(item,i) in list" :key="item.id" @click="remove(i)">
{{item.id}}...................{{item.name}}</li>
</transition-group>
19.动画name属性
<style>
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(100px);
}
.fade-enter-active,
.fade-leave-active {
transition: all 1s ease;
}
</style>
<transition name="fade">
<h3 v-show="flag2">222222222</h3>
</transition>
20.创建全局组件的方式
<script>
let com= Vue.extend({
tempale:'<div>content</div>'
})
// 注:这玩意如果是大写(组件名称),则在标签上必须将大写字母改为小写,在其前面加上-
Vue.component('组件名称','组件构造函数')
</script>
<script>
Vue.component('组件名称',{
tempale:'<div>content</div>'
})
</script>
<script>
Vue.component('组件名称',{
tempale:'#id'
})
</script>
21.私有组件的概念
<template id='tmpl'>
<div>
<h3>自定义组件</h3>
<p>打王者闪退</p>
</div>
</template>
<script>
var vue = new Vue({
el: '#container',
data: {},
methods: {},
components:{
'com':{//组件名称
template:'tmpl'//组件解构
}
}
});
</script>
22.全局组件的概念
Vue.component('com',{
template:'<h3>data</h3>',
data(){
return{
}
},
methods:{
}
})
23.切换多个组件
<component :is="componentName"></component>
24.子组件向父组件传递数据
<com1 @fn="show"></com1>
<script>
let vue=new Vue({
data:{
},
methods:{
//接收数据
show(data) {
console.log("show..show...show.oh");
//赋值
this.age = data;
console.log(this.age);
}
},
components:{
'com1':{
template:`<input type="button" value="我是一个按钮" @click="btnClick"/>`,
data(){
return {
age: 22
}
},
methods:{
btnClick(){
//子组件向父组件传递数据
//父组件向子组件传递方法
this.$emit('fn',this.age)
}
}
}
}
})
</script>
25.父组件向子组件传递值
<com :msg='name'></com>
<script>
let vue=new Vue({
data:{
name:'data'
},
components:{
'com':{
template:"<h3>这是子组件中的标题:{{msg}}</h3>",
porps:['msg']
}
}
})
</script>
26.ref
<h3 ref="reference"></h3>
<script>
new Vue({
...
getInfo(){
//类似于let res= document.getElementsByTagName("h3")[0].innerHTML;
this.$refs.reference.innerHTML
}
})
//注:ref可以改变组件中msg的值,可以调用方法
</script>
26.1 使用ref获取组件上的方法
<input type="button" value="获取页面上的组件" @click="getCom">
<com1 ref='mycom'></com1>
<script>
Vue.component("com1", {
template: "<h3 >这是一个小组件{{msg}}</h3>",
data() {
return {
msg: "ok",
}
},
methods: {
show() {
console.log("子组件show.............");
}
},
})
var vue = new Vue({
el: '#container',
data: {},
methods: {
getCom() {
this.$refs.mycom.msg = 123;//改变com1组件上的值
this.$refs.mycom.show(); //调用com1组件上的方法
}
}
});
</script>
27.data和props的区别
//data中的数据是子组件私有的,是可读可写的
//props中的数据是父组件传递过来的,可读不可写
28.hash
<a href="#/b">a</a>
<a href="#/a">b</a>
//这是HTML5新增事件,当hash值发生改变会触发这个事件
window.onhashchange=function(){
}
29.router
<style>
/* 被选中路由的样式 */
.router-link-active {
color: red;
font-size: 20px;
}
.ma-active {
color: orange;
font-size: 30px;
}
</style>
<router-link to='/login'>登录</router-link>
<router-link to="/reg">注册</router-link>
<transition>
<router-view></router-view>
</transition>
<script>
let login={
template:'data'
}
let router=new VueRouter({
routes:[
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/reg',component:reg}
],
// 另一种设置样式的方式
linkActiveClass: className
})
new Vue({
...
router:router
})
</script>
30.query路由传参
//<router-link to="/login?id=10">登录</router-link>
{ path: '/login', component: login },
created(){
//获取传入的值
console.log(this.$route.query.id)
}
31.params路由传参
// <router-link to="/login/10/zs">登录</router-link>
{ path: '/login/:id/:name', component: login },
created(){
//获取传入的值
console.log(this.$route.params.id)
}
32.路由中使用props获取参数
routes:[
{ path: '/login/:id/:name', component: login, props: true },
]
const login={
template:login,
prop:["name","id"],
created(){
console.log(this.name,this.id);
}
}
33.组件嵌套
{
path: "/account", component: account, children: [
{ path: "login", component: login },
{ path: "reg", component: reg },
]
},
34.命名视图
<router-view name="top"></router-view>
<div class="contain">
<router-view name="left"></router-view>
<router-view name="right"></router-view>
</div>
<router-view name="bottom"></router-view>
<script>
path: "/", components: {
"top": header,
"left": sidebar,
"right": content,
"bottom": footer
}
</script>
35.watch
firstName: <input type="text" v-model="firstName">
+lastName: <input type="text" v-model="lastName">
= <input type="text" v-model="resName">
new Vue({
data: {
firstName: "",
lastName: "",
resName: ""
},
watch:{
//监听数据的改变
//watch可以监听当前vm实例中的所有属性
firstName(newval,oldval) {//当前值和上一次的值
this.resName = this.firstName +"-"+ this.lastName;
console.log(oldval,newval);
},
}
})
36.computed
//computed擅长处理的场景:一个数据受多个数据影响
//这个resName就是计算属性,在页面中,使用计算属性的时候,永远把它当做普通属性来使用
//只要计算属性的()中,所依赖的任何数据发生了改变,则会触发计算属性的重新求值
new Vue({
...
computed:{
"resName": function () {
//计算属性的值,如果被第一次计算后,没有发生过变化,则会把第一次的值,缓存起来,
//供后续使用(无论多少个p标签,里面的resName已经缓存,之后输出一次)
console.log("a");
return this.firstName + "-" + this.lastName;
}
})
37.render
const login = {
template: "<h3>rander渲染组件</h3>"
}
new Vue({
...
//render会把之前的内容清除掉,然后只显示render这个函数的组件
render(creatElements) {
return creatElements(login);
},
})