目录
- 1 一、入门
- 1.1 组件
- 1.2 组件的嵌套&组件数据data要写成方法,返回数据
- 1.3 单文件组件(html+css+js 都写在同一个页面,并且以vue为后缀)
- 1.4 页面缓存
- 1.5 动态改变html属性:(v-bind:指定属性);简写(:指定属性}
- 1.6 html输出标签 与 text 输出标签
- 1.7 循环输出指令:v-for
- 1.8 事件绑定指令: (v-on:事件=”方法”),简写(@事件=”方法”)
- 1.9 条件指令:v-if v-else
- 1.10 显示指令:v-show
- 1.11 数据绑定:v-model 实时更新
- 1.12 动态引用组件: (:is=”组件名”)
- 1.13 vue的计算属性:computed
- 1.14 vue 属性监听:watch
- 1.15 子父组件互传数据:
- 1.16 动画标签:transition
- 2 路由vue-router
- 3 状态管理:vuex
- 4 api请求:axios
一、入门
1 2 3 |
<div id="app"> {{ message }} </div> |
1 2 3 4 5 6 |
var app = new Vue({ el: '#app',//绑定元素,指定渲染位置 data: {//页面输出的数据 message: 'Hello Vue!' } }) |
组件
1 2 3 |
<div id=app> <myheader></myheader>//组件在这里渲染 </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var myheader = { template:'<p>我是模板,我是页面的一部分{{msg}}</p>' data:{ msg:'这是数据' //给模板输出数据 } } new Vue({ el: '#app', //组件 components: { 'myheader':myheader } }) |
组件的嵌套&组件数据data要写成方法,返回数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
var myheader-child = { template:'<p>我是子模板,我是父页面的一部分{{msg}}</p>', data:function(){ return { msg:'这是数据' //给模板输出数据 } } } } var myheader = { template:'<p>我是模板,我是页面的一部分{{msg}}</p>', data:function(){ return { msg:'这是数据' //给模板输出数据 } } }, //子组件,组件可以嵌套 components: { 'myheader-child':myheader-child } } new Vue({ el: '#app', //组件 components: { 'myheader':myheader } }) |
单文件组件(html+css+js 都写在同一个页面,并且以vue为后缀)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//<template> 模板定义区域,渲染的是这部分内容 <template> <div id="second"> {{msg}} </div> </template> //vue js代码 <script> export default { name: 'second', data () { return { msg: '这是转跳页面' } } } </script> //css代码,scoped:代表作用域,这段css只在这个页面生效 <style scoped> .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; } </style> |
页面指令
页面缓存
1 2 3 4 |
//<keep-alive>包裹的组件,缓存下来 <keep-alive> <myheader></myheader> </keep-alive> |
动态改变html属性:(v-bind:指定属性);简写(:指定属性}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div id="second"> <p v-bind:class="red">fffff</p> <p :class="red">fffff</p> <p :title="red">title</p> </div> </template> <script> export default { name: 'second', data () { return { red: 'red' } } } </script> |
输出多个class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<template> <div id="second"> <p :class=[classA,classB]>fffff</p> </div> </template> <script> export default { name: 'second', data () { return { classA: 'red', classB: 'green', } } } </script> |
条件输出class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template> <div id="second"> <p :class=[classA,{'green':hasErr}]>fffff</p> </div> </template> <script> export default { name: 'second', data () { return { classA: 'red', classB: 'green', hasErr: true, } } } </script> |
html输出标签 与 text 输出标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div id="second"> <p v-html="red"></p>//输出 red <p v-text="red"></p>//输出 <span>red</span> </div> </template> <script> export default { name: 'second', data () { return { red: '<span>red</span>' } } } </script> |
循环输出指令:v-for
数组循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul> var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) |
数组循环索引 index
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<ul id="example-2"> <li v-for="(item, index) in items"> {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul> var example2 = new Vue({ el: '#example-2', data: { parentMessage: 'Parent', items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) |
对象循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<ul id="v-for-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul> new Vue({ el: '#v-for-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } }) |
你也可以提供第二个的参数为键名:
1 2 3 |
<div v-for="(value, key) in object"> {{ key }}: {{ value }} </div> |
第三个参数为索引:
注意:数组的索引是 index ,对象的索引是key
v-for写在那个标签上,就循环那个标签
事件绑定指令: (v-on:事件=”方法”),简写(@事件=”方法”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<template> <div id="second"> <botton @click="addItem"></botton> </div> </template> <script> export default { name: 'second', list:[ { name:'abc', age:'10' }, { name:'def', age:'11' }, ], methods:{ addItem(){ //往list临时动态添加数据 this.list.push({ name:'ghi', age:'13' }) //修改list某个数据 Vue.set(this.list,1,{ name:'ghi', age:'13' }) } } } </script> |
注意:还有数据动态添加,修改指定数据
Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
你打开控制台,然后用前面例子的 items
数组调用变异方法:example1.items.push({ message: 'Baz' })
。
条件指令:v-if v-else
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div id="second"> //如果true就输出p标签 <p v-if="result">partA</p> </div> </template> <script> export default { name: 'second', data(){ return{ result:true } } } </script> |
显示指令:v-show
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div id="second"> //如果true就显示p标签 <p v-show="result">partA</p> </div> </template> <script> export default { name: 'second', data(){ return{ result:true } } } </script> |
数据绑定:v-model 实时更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<template> <div id="second"> //如果true就显示p标签 <input v-model="result" type="text"/> {{result}} </div> </template> <script> export default { name: 'second', data(){ return{ result:'' } } } </script> |
如果是checkbox、radio等多选,data中的初始值为空数组
v-model.lazy=”” 延迟加载,不在输入模式,才刷新数据
v-model.number=”” 声明为数字类型
动态引用组件: (:is=”组件名”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> <div id="second"> <p :is="comToRender" ></p> </div> </template> <script> //引入组件 import comA from '@/components/a' export default { name: 'second', //注册组件 components:{ comA }, data(){ return{ comToRender:'com-a'//这样就可以动态渲染不同组件 } } } </script> |
vue的计算属性:computed
监听data的值,如果data值有变化,会触动此属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> <div id="second"> //如果true就显示p标签 <input v-model="result" type="text"/> {{ myValueWhitoutNum}} </div> </template> <script> export default { name: 'second', data(){ return{ result:''//这个数据不变动,不会触发computed里的方法 } }, computed:{ myValueWhitoutNum(){ return this.result.replace(/\d/g,'') } } } </script> |
vue 属性监听:watch
每当有属性的变化,就会触发此属性里的自定义方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<template> <div id="second"> //如果true就显示p标签 <input v-model="result" type="text"/> {{ myValueWhitoutNum}} </div> </template> <script> export default { name: 'second', data(){ return{ result:''//这个数据不变动,不会触发computed里的方法 } }, watch:{ //oldValue 变动之前的值 //val 变动之后的值 result:function(val,oldValue){ console.log(val,oldValue); } } } </script> |
子父组件互传数据:
父传子,父在模板渲染标签处传值,子使用props属性接收
子传父,子定义一个事件,调用vue的emit方法,返回数据,父在组件渲染处,定义一个约定的事件接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<template> <div id="second"> //向子组件传 number=5 //使用约定事件 @my-event="getMyEvent" 接收子组件数据 <com-a number=5 @my-event="getMyEvent"></com-a> </div> </template> <script> //引入组件 import comA from '@/components/a' export default { name: 'second', //注册组件 components:{ comA }, data(){ return{ comToRender:'com-a'//这样就可以动态渲染不同组件 } }, methods:{ //hello是子组件传值的key getMyEvent(hello){ console.log(hello); } } } </script> |
子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<template> <div id="second"> {{number-a}} //子向父传值 <button @click="emitMyEvent">emit</button> </div> </template> <script> export default { //props接收父传来的值 //支持数组和对象 props:{ number-a:number }, data(){ return{ hello:'hello world' } }, methods:{ emitMyEvent(){ //使用vue的emit方法给父传值 //my-event,与父约好的事件名 //this.hello,把data的hello的值传过去 this.$emit('my-event',this.hello); } } } </script> |
父组件向子组件插入内容,使用插槽标签:slot
父组件
1 2 3 4 5 |
<template> <div id="second"> <slot name="header">这是公共头部</slot> </div> </template> |
子组件
1 2 3 4 5 6 |
<template> <div id="second"> //等待父插入标记名为header的内容 <slot name="header"></slot> </div> </template> |
动画标签:transition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<div id="demo"> <button v-on:click="show = !show"> Toggle </button> <transition name="fade" mode="out-in"> <p v-if="show">hello</p> </transition> </div> new Vue({ el: '#demo', data: { show: true } }) .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; } |
过度标签相同,要用key区别
1 2 3 4 |
<transition name="fade" mode="out-in"> <p v-if="show" key="1">hello</p> <p v-if="!show" key="2">welcome</p> </transition> |
路由vue-router
引入路由
import Router from ‘vue-router’
全局使用
Vue.use(Router)
注册路由
new Vue({
router,
})
使用路由
1 2 3 4 5 6 7 8 9 |
let router = new Router({ routes:[ { path:'/apple', component:Apple } ] }) |
指定路由转跳后,组件显示的位置:标签router-view
1 2 3 4 5 |
<template> <div class="friutColor"> <router-view><router-view> </div> </template> |
路由连接:标签router-link
1 2 3 4 5 |
<template> <div class="friutColor"> <router-link :to="{path:'apple'}">apple<router-link> </div> </template> |
路由传参
1 2 3 4 5 6 7 8 9 |
let router = new Router({ routes:[ { path:'/apple/:color', component:Apple } ] }) |
接收路由参数: $route.params
方法
1 2 3 4 5 6 |
methods:{ getParams(){ console.log(this.$route.params) } } |
组件
1 2 3 4 5 |
<template> <div class="friutColor"> {{$route.params.参数的key}} </div> </template> |
路由嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let router = new Router({ routes:[ {//http://localhost/apple/red path:'/apple', component:Apple, children:[ { path:'red',//最前面不要有'/',不是从根路由开始 component:redApple, } ] } ] }) |
路由url模式
1 2 3 4 5 6 7 8 9 10 11 |
let router = new Router({ mode:'history',//平常使用的url地址,默认url,域名后紧跟# routes:[ { path:'/apple', component:Apple, } ] }) |
路由重定向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let router = new Router({ routes:[ { path:'/', redirect:'/apple'//路由重定向 }, { path:'/apple', component:Apple, } ] }) |
路由命名
1 2 3 4 5 6 7 8 9 10 11 |
let router = new Router({ routes:[ { path:'/apple', component:Apple, name:'Apple'//路由命名 } ] }) |
路由视图命名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
let router = new Router({ routes:[ { path:'/apple', component:{//路由视图命名 viewA:Apple, viewB:redApple }, name:'Apple' } ] }) |
1 2 3 4 5 6 |
<template> <div class="friutColor"> <router-view name="viewA"></router-view> <router-view name="viewB"></router-view> </div> </template> |
编程式路由
router.push({path:’apple’});
路由转跳前执行的操作
router.beforEach()
状态管理:vuex
一处组件状态改变,全局对应的组件同步改变。
比如,一处的购物车组件的价格改变,所有购物车组件同步改变
vex的核心是store(数据中心)。
一处组件改变,导致store同步改变,再由store通知所有组件同步改变
引入vuex
import Vuex from ‘vuex’
全局使用
Vue.use(Vuex)
实例vuex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
let store = new Vuex.Store({ state:{ totalPrice:0 }, getters:{//获取state结果集 getTotal(state){ return state.totalPrice } }, mutations:{//同步获取数据 increment(state,price){ state.totalPrice+=price }, decrement(state,price){ state.totalPrice-=price } }, actions:{//异步获取数据 increase(context,price){ context.commit('increment',price) } } }) |
注册vuex
new Vue({
store,
})
vuexs实例,核心$store
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<template> <div class="apple"> <h1>{{msg}}</h1> <button @click="addOne">加 1 </button> <button @click="minusOne">减 1 </button> </div> </template> <script> export default { name: 'apple', data () { return { msg: '这是apple页面', price:5 } }, methods:{ addOne(){ //this.$store.commit('increment',this.price)// vuex 的 mutations 同步 this.$store.dispatch('increase',this.price)// vuex 的 actions 异步 }, minusOne(){ this.$store.commit('decrement',this.price) } } } </script> |
api请求:axios
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
<div id="app" class="container"> <h1>axios插件讲解</h1> <a href="javascript:;" class="btn btn-primary" v-on:click="get">Get请求</a> <a href="javascript:;" class="btn btn-primary" @click="post">Post请求</a> <a href="javascript:;" class="btn btn-primary" @click="http">http</a> <div> <span>{{msg}}</span> </div> </div> <script> new Vue({ el:"#app", data:{ msg:'' }, mounted: function () { //全局拦截器 axios.interceptors.request.use(function (config) { //请求前执行的动作 console.log("request init."); return config; }) axios.interceptors.response.use(function (response) { //响应前执行的动作 console.log("response init."); return response; }) }, methods:{ get: function () { axios.get("../package1.json",{ params:{ userId:"999" }, headers:{ token:"jack" } }).then(res=>{ this.msg = res.data; }).catch(function (error) { console.log("error init."+error) }); }, post: function () { axios.post("../package.json",{ userId:"888" },{ headers:{ token:"tom" } }).then(res=>{ this.msg = res.data; }).catch(function (error) { }) }, http: function () { axios({ url:"../package.json", method:"get", data:{//post用data userId:"101" }, params:{//get用params userId:"102" }, headers:{ token:"http-test" } }).then(res=>{ this.msg = res.data; }) } } }); </script> |