父 => 子 传值
父组件中定义属性 <com-a :aaa="parm">
,子组件通过 props:['aaa']
获取
子 => 父 传值
父组件中自定义事件 <com-a @aaa="parm">
,子组件通过 methods:{this.$emit('aaa',要传的值)}
向父元素传值
v-test / v-html
v-test
:所有内容转换为字符串输出
v-html
:如果有标签就按标签转换
组件中为什么 data(){return{}}
而不是 data:{}
防止修改 data
内容时由于引用传值导致误改了其他 template
组件
v-if / v-show
v-if
标签有 /
没有
v-show
通过 display:none
控制
其他
<template lang="jade">
使用 jade
模板
<style lang="less">
使用 less
语法
watch
属性监听
data(){
abc:'',
}
watch:{
abc:function(val,oldval){
// 当 abc 发生变化时触发函数,可通过两个参数获取到变化前后的值
}
}
计算属性有两种方法(视频第三章 5-7 节后半部分)
computed
- 自定义方法,实时调用
插槽
-
<slot>
:将要插入的内容放到子组件标签中,在子组件中使用<slot></slot>
。 - 可命名 :
<p slot="head"></p>
,对应子组件中<slot name="head"></slot>
缓存标签内的信息
<keep-alive></keep-alive>
组件的动态切换
<p :is="currentView"></p>
data(){
return{
currentView:'com-a'
}
}
通过对 currentView
动态切换实现组件切换,这里 com-a
是写好的组件
过渡效果
- 通过
<transition name="aa">
内置组件,组件可以命名,可以通过两种方式实现,需要给过渡的作用标签加上v-show
或者v-if
- CSS 过渡
- JS 过渡
- CSS 过渡 官网有个图非常直观,对比官网例子
整个过程可分为:
1.刚开始淡入
2.完全显示
3.完全消失
.fade-enter
刚要进入的瞬间 => 1
.fade-leave-to
完全离开的瞬间 => 3
.fade-enter-active { // 进入的过程
transition: all .5s ease;
}
.fade-leave-active { // 离开的过程
transition: all .5s ease;
}
.fade-enter { // 刚进入的瞬间
transform:translateX(200px);
opacity: 0
}
.fade-leave-to { // 离开终点的瞬间
transform: translateX(200px);
opacity: 0
}
- 当使用
is 属性 + transition
实现组件切换的过渡效果时,<transition>
有个默认的属性mode="in-out"
,这样的效果是:新组件先进入,而旧组件后消失,这样会有个效果上的不和谐。改成mode="out-in"
就好 - 多个标签或者组件进行过渡切换时,如果标签名相同,比如两个
<p>
标签切换显示隐藏,并且标签上没有key
属性时,切换效果会无效。这是由于vue
最大化重用标签或组件,实际上是针对一个<p>
标签进行操作,所以需要在两个<p>
标签加上不同的key
属性作为区分,避免重用 - 当
<transition>
与<keep-alive>
共用时,需要<transition>
在外
自定义指令
- 局部自定义指令 - 写在某个组件中
- 全局自定义指令 - 写在根节点实例化时
new Vue
时(main.js
中)<p v-color="'red'">自定义指令</p> // 注意传的是字符串red,所以写的是 'red'(带引号) ... directives:{ color:function(el,binding){ el.style.color = binding.value } }
-
el
:指令所绑定的元素,可以用来直接操作DOM
-
binding
:一个对象,包含name
,value
等多个属性 - 指令定义函数提供了几个钩子函数(见官网):
-
bind
:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
-
插件
- 安装方法
-
npm install vue-router --save
(--save
是安装插件后,让package.json
中同步更新) - 在全局中引用
vue-router
-
main.js
中最上面import VueRouter from 'vue-router'
-
main.js
中加入Vue.use(VueRouter)
-
-
Vue - cli
-
npm install vue-cli -g
全局安装 -
vue init webpack
新建项目名 初始化项目 -
npm install
安装项目依赖 -
npm run dev
在localhost
启动测试服务器 -
npm run build
(部署)
Vue - router
写在
<router-link>
中的是 声明式导航,另一种是写在
JS
中的 编程式导航this.$route.path
// 全部的路径值-
this.$route.params
// 带:
的部分
console.log(this.$route.params) // Object {color: "xxxx", name: "xxx"}
{ path: '/apple/:color/ok/:name', name: 'apple', component: Apple }
-
子路由的匹配方式
- 如果配置中设置了
name
属性(也就是 命名路由),则也可以在<router-link :to="{name:"xxx"}" tag="li">
中通过name
属性调用。其中tag
属性可以将默认的<a>
改为<li>
。 - 命名路由 / 命名视图
// 命名路由 <router-link :to="{name:'apple2'}"> 命名路由 </router-link> { path: '/apple', name: 'apple2', component: Apple, children:[ { path:'applechild', component:applechild }] }
// 命名视图 <router-view name="viewA"></router-view> <router-view name="viewB"></router-view> // index.js 中 path: '/apple', name: 'apple2', components: { viewA: Apple, viewB: Banana },
- 如果配置中设置了
可以在标签中通过类似
<p>{{$route.params.color}}</p>
语法调用
此外,一旦添加了诸如:color
这种参数,<router-link>
中to
属性值必须格式完全匹配index.js
中的路径地址(如上例中,url
地址必须为
/apple/param1/ok/param2
),否则不会跳转到响应的组件,注意看to
需不需要加:
-
正常跳转的时候会有
hash
的#
,通过在index.js
中设置mode: 'history'
,即可export default new Router({ mode:'history', routes:[{ ... }] })
-
编程式导航
- 在
index.js
中通过router.push({path:'xxx'})
实现 - 也可以配合
Vue-router
的钩子函数,比如router.beforeEach()
可以实现跳转之前先执行一个判断之类的
- 在
-
重定向
- 当访问根目录时,自动跳转到
apple
路由
{ path: '/', redirect:'apple', // 重定向 name: 'Hello', component: Hello },
- 当访问根目录时,自动跳转到
router-link-active
Vuex
$ cnpm install vuex --save
- 在
main.js
(入口文件)中引入
// main.js
import Vuex from 'vuex' // 1. 引入
Vue use (Vuex) // 2. 注册
let store = new Vuex.store({
// 3. 配置
mutations:{
fn1(){
...
},
fn2(){
...
},
}
})
new Vue({
el: '#app',
router,
store, // 4. 全局使用
template: '<App/>',
components: { App }
})
// 子组件中
this.$store.state // 5. 在子组件中调用 store 中的状态
this.$store.commit('fn1',传值) // 6. 可以通过 commit 调用 store 中 mutations 内的各种方法,进而改变 store 中的参数
this.$store.commit('fn2',传值)
- 关于
mutations
和actions
mutations
用来直接管理state
的,因此mutations
是 同步 的(mutations
内的方法是一行一行执行)
actions
用来调用mutations
中的方法,是 异步 的(actions
中的某个方法在执行的过程中可以去请求个数据啥的,不耽误后面代码执行)// <template> 中通过 dispatch 调用 actions 中的方法 plus(){ this.$store.dispatch('increase',100) }, // actions 中 通过 commit 调用 mutations 中的方法 mutations:{ increment (state,price){ state.totalPrice += price }, decrement (state,price){ state.totalPrice -= price }, }, actions:{ increase (context,price){ context.commit('increment',price) } }
-
getters
:store
中的一个属性。可以通过getters
获取到state
中的某个状态,进行进一步的操作,比如:state
中有个数组,使用getters
获取到这个数组,然后对数组进行过滤或者计算啥的let store = new Vuex.Store({ state: { totalPrice:0 }, getters:{ way(state){ return state.totalPrice; } }, // <template> 中调用 this.$store.getters.xxx
-
modules
:Talk is cheap// 定义 const modulesA = { state:{...}, mutations:{...}, actions:{...}, getters:{...}, } const modulesB = { state:{...}, mutations:{...}, actions:{...}, getters:{...}, } // 配置 let store = new Vuex.Store({ modules:{ a:modulesA, b:modulesB } }) // 调用 store.state.a // moduleA's state store.state.b // moduleB's state
- 官方推荐使用
Vuex
项目的结构├── index.html ├── main.js ├── api │ └── ... # 抽取出API请求 ├── components │ ├── App.vue │ └── ... └── store ├── index.js # 我们组装模块并导出 store 的地方 ├── actions.js # 根级别的 action ├── mutations.js # 根级别的 mutation └── modules ├── cart.js # 购物车模块 └── products.js # 产品模块
关于双向绑定
- 先进行初始化的数据绑定,将实际的
DOM
节点劫持到
documentFragment
中 - 响应式数据绑定,主要是实现
input
输入内容时,data
跟着变化,需要做的就是通过ES5
的defineProperty
进行数据的观察和修改 - 实现
data
改变同步页面中的数据更新,观察者模式,可以是多个观察者对数据进行监听,当数据改变后,会触发一个更新的函数,进而实现页面的更新