mvvm 框架
1.了解
Vue React Angular
MVC Model View Controller
MVVM Model View ViewModel
mvvm定位 Model <=> ViewModel <=> View Model 与 View 是分离的
MVC 与 MVVM 区别
在MVC里,View是可以直接访问Model的。Model不依赖View,而View依赖于Model。更改view更难。
在MVVM里, View(页面)与Model(数据)是分离的。
2.双向绑定的原理
- data=>view data改变会使view变化
view=>data view变化也会改变data
绑定 => 自动化处理,不需要人为关心。 原理
data => view Object.defineProperty get/set操作 依靠它 监听data的变化
view => data input事件,只不过框架执行了我们看不到。123456var obj = { };// 为obj定义一个名为 hello 的访问器属性Object.defineProperty(obj, "hello", {get: function () {return sth},set: function (val) {/* do sth */}})object.defineProperty 与 reflect.defineProperty 区别
object.defineProperty 返回的是一个对象 reflect.defineProperty 返回Boolean值作为成功的状态
object.defineProperty 还可以用来 深度复制
let desc = Object.getOwnPropertyDescriptor(source,key);
Object.defineProperty(target,key,desc);
3.设计模式
观察者模式 data => Observer Dep Watcher => View
4.生命周期
Vue
beforeCreate => el与data并未初始化 => 可以在这加loading事件。
created => 完成了data数据的初始化。 => 做一些初始化,实现函数自执行。
beforeMount => 完成了el和data初始化
mounted => 完成挂载 => 向后端发起请求,那回数据,配合路由钩子做事
beforeDestory
destoryed => 当前组件已被删除,清空相关内容。
beforeUpdate
updated
React
static defaultProps
constructor => 接收父组件的props,context
componentWillMount => 组件刚经历constructor,初始完数据 组件还未render,dom未渲染
render
componentDidMount => 组件第一次渲染完成,此时dom节点已经生成,可以调用ajax,返回数据setState后组件会重新渲染
componentWillUnmount => clear 组件中的定时器 setTimeout,setInterval,移除组件监听。
componentWillReceiveProps
shouldCompoentUpdate
componentWillUpdate
render
componentDidUpdate
5. 路由
vue-router
|
|
vue 比 react 多了一个 router-view
123
<keep-alive> <router-view :seller="seller"></router-view></keep-alive>
keep-alive 作用
把切换出去的组件保存到内存中,保留它的状态或避免重复渲染。
链接(重定向)
router-link
就变成li标签了
react-router-dom
|
|
链接(重定向)
import {Link} from ‘react-router-dom’;
我的私人音乐坊 &qt;6. params
vue
获取params => this.$route.params
react
获取params => this.props.params
7. 获取DOM
1.vue=> this.$ref.name
2.react => this.ref.name
8. 数据请求
vue
vue-resource
import VueResource from 'vue-resource';
app.use(VueResource);
this.$http.get('/goods/list')
.then((response) => {
response = response.body;
if (response.status === '0') {
this.goods = response.result.list;
this.$nextTick(() => {
this._initScroll();
this._calculateHeight();
});
}
});
跨域:代理 proxyTable
axios => vue2.0以后用axios
import axios from 'axios';
axios.get('/users/addressList').then((response)=>{
var res = response.data;
this.addressList = res.result;
this.addressList.forEach((item,index)=>{
if(item.isDefault){
this.currentIndex = index;
this.selectedAddressId = item.addressId;
}
})
})
跨域
跨域post实例,用到了qs组件来避开ajax信使请求,并兼容Android。
import axios from 'axios';
import qs from 'qs';
axios.post('http://www.xyz.com/request', qs.stringify(params))
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
react => fetch
var myFetchOptions = {
method: 'GET'
};
fetch("http://newsapi.gugujiankong.com/Handler.ashx?action=uc&userid=" + localStorage.React_userid + "&uniquekey=" + this.props.uniquekey, myFetchOptions)
.then(response=>response.json())
.then(json=>{
//收藏成功以后进行一下全局的提醒
notification['success']({message:'ReactNews提醒',description:'收藏此文章成功'});
})
fetch 跨域 => 数据模拟我选择代理方式proxy || fetch-jsonp 插件实现jsonp
"proxy": {
"/api": {
"target": "http://localhost:4000",
"secure": false
},
"/tuan": {
"target": "http://m.dianping.com",
"secure": false
}
}
9. 组件间数据传递
vue
父子组件
父 => 子
父组件中<food :food="selectedFood"></food>
子组件接收
props:{
food:{
type:Object
}
}
子组件使用数据方式 this.food (即与data中数据使用方式相同)
子 => 父
this.$emit('add',target/msg) => 触发父组件中add事件,执行add绑定的函数。
子组件之间数据传递 eventBus or vuex全局
evetnBus
功能:实现组件间通信,点击外部关闭select=>同一时间最多有一个select处于下拉状态
建立eventBus.js
import Vue from 'vue'
const eventBus = new Vue()
export { eventBus }
全局组件中定义click事件
resetComponent() { eventBus.$emit('reset-component') }
具有select的组件中触发eventBus
mounted () {
eventBus.$on('reset-component', () => {
this.isDrop = false
})
// 每一个select组件 只要触发reset-component 就会使this.isDrop重置
}
toggleDrop(e) {
e.stopPropagation() //注意要阻止冒泡
eventBus.$emit('reset-component') //多个select 点击别的select也触发事件
this.isDrop = !this.isDrop
}
vuex
核心 State Getter Mutation Action Module
actions(commit) => mutations(同步函数) => state(改变state) => components(自动更新componets)
1.import Vuex from 'vuex';
2. Vue.use(Vuex);
3. const store = new Vuex.Store({
state:{
userName:'',
cartCount:0
},
mutations:{
updateUserInfo(state,userName){
state.userName = userName;
},
updateCartCount(state,cartCount){
state.cartCount += cartCount;
},
initCartCount(state,cartCount){
state.cartCount = cartCount;
}
}
})
4.new Vue({store});
const store = new Vuex.Store({
state:{
userName:'',
cartCount:0
},
mutations:{
updateUserInfo(state,userName){
state.userName = userName;
},
updateCartCount(state,cartCount){
state.cartCount += cartCount;
},
initCartCount(state,cartCount){
state.cartCount = cartCount;
}
}
})
<!-- 在各个组件中都可以使用 this.$store.commit(mutations中的方法) 来更新components -->
this.$store.commit("updateCartCount",-1);
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
应用层级的状态应该集中到单个 store 对象中。
提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
异步逻辑都应该封装到 action 里面。
State 作为一个“唯一数据源 (SSOT)”而存在
从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
computed: {
count () {
return store.state.count
}
}
mapState: mapGetters...同理
import { mapState } from 'vuex'
...mapState(...)
Getter 有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
触发 store.commit('increment')
注意事项
最好提前在你的 store 中初始化好所有所需属性。
当需要在对象上添加新属性时,你应该
使用 Vue.set(obj, 'newProp', 123), 或者
以新对象替换老对象。例如,利用 stage-3 的对象展开运算符我们可以这样写:
state.obj = { ...state.obj, newProp: 123 }
一条重要的原则就是要记住 mutation 必须是同步函数
Action Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
Action 通过 store.commit 方法触发:
store.commit('increment')
react
父子组件数据传递
- 父 => 子 通过props传递
父组件
子组件接收 this.props.food
vue 与 react 数据使用格式区别
vue
1.html中=>直接使用 data/porps中数据名称。
2.js中=> this.数据名称
react
1.html/js中 => this.props.数据名称/this.state.数据名称
- 子 => 父 通过函数 父组件中函数传递给子组件,子组件中返回数据给父组件
|
|
- 子组件间通信
1.子 => 父 => 子
子组件传给父组件 父组件根据子组件数据改变state, state改变重新render下面的子组件
由于 Parent 的 state 发生变化,会触发 Parent 及从属于 Parent 的子组件的生命周期,所以我们在控制台中可以看到,在各个组件中的 componentDidUpdate 方法均被触发。所以有别的就用别的。
2.eventProxy
eventProxy 中,总共有 on、one、off、trigger 这 4 个函数:
on、one:on 与 one 函数用于订阅者监听相应的事件,并将事件响应时的函数作为参数,on 与 one 的唯一区别就是,使用 one 进行订阅的函数,只会触发一次,而 使用 on 进行订阅的函数,每次事件发生相应时都会被触发。
trigger:trigger 用于发布者发布事件,将除第一参数(事件名)的其他参数,作为新的参数,触发使用 one 与 on 进行订阅的函数。
off:用于解除所有订阅了某个事件的所有函数。
|
|
栗子 => usercenter页面改变数据 更新header 登录状态;trigger =>触发 on事件
header => 注册on事件
usercenter => 触发 trigger
- redux
|
|
Provider connect
Provider 内的组件要必须被 connect 过的
connect => mapStateToProps(state,ownProps)/mapDispatchToProps(dispatch,ownProps)