-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vue与React #1
Comments
关于vue中route路由中的的设置和获取并且多参数使用query设置和获取首先query的路由样子为
路由的获取:
路由的跳转:
使用params设置和获取首先params的路由样子为
路由的获取
路由的跳转
|
Vue中的数据操作Vue包装了数个数组操作函数,使用这些方法操作的数组去,其数据变动时会被vue监测:
vue2.0还增加个方法可以观测Vue.set(items, indexOfItem, newValue) Vue中自定义组件双向绑定//父组件
<template>
<abcde v-model="text3" />
<p>{{String(text3)}}</p>
</template>
<script>
export default {
data(){
return{
text3 = 233
}
}
</script> //子组件abcde
<template>
<div>
<button @click="plus">加</button>
<button @click="minus">减</button>
<button @click="equal">赋值</button>
</div>
</template>
<script>
export default {
props:['value'],
computed:{
ccc:{
get:function(){
return this.value;
},
set:function(v){
this.$emit('input',v)
}
}
},
methods:{
plus(){
this.ccc++;
},
minus(){
this.ccc--;
},
equal(){
this.ccc = 250
}
}
}
</script> |
Redux vs VUEX 对比分析store和state是最基本的概念,VUEX没有做出改变。其实VUEX对整个框架思想并没有任何改变,只是某些内容变化了名称或者叫法,通过改名,以图在一些细节概念上有所区分。
总的来说,VUEX通过弱化概念,在任何东西都没做实质性削减的基础上,使得整套框架更易于理解了。 另外VUEX支持getter,运行中是带缓存的,算是对提升性能方面做了些优化工作,言外之意也是鼓励大家多使用getter。 |
Redux中action重名的问题解决方法// a.js
export const CLEARDATA= 'CLEARDATA';
// b.js
export const CLEARDATA= 'CLEARDATA'; 解决方法 // a.js
export const CLEARDATA= Symbol('CLEARDATA');
// b.js
export const CLEARDATA= Symbol('CLEARDATA'); 2.命名时加入“名空间”限制 // a.js
export const CLEARDATA= 'a/CLEARDATA';
// b.js
export const CLEARDATA= 'b/CLEARDATA'; |
关于React中的super参数propsconstructor() {
super()
console.log(this.props)//undefined
console.log(props)//error
}
constructor(props) {
super()
console.log(this.props)//undefined
console.log(props)//{ icon: 'home', … }
}
constructor(props) {
super(props)
console.log(this.props)//{ icon: 'home', … }
console.log(props)//{ icon: 'home', … }
} 所以在子类组件的构造函数constructor和super中加入参数props,就是为了让子类可以访问this.props, |
vue 页面加载完成,input自动获得焦点需求:当页面加载完毕时,自动获得焦点 <input ref="aaa" value="123123"/> var app = new Vue({
el: '#app',
mounted(){
this.$refs.aaa.focus();
//这里光标会在文本最前方,需要单独写方法,移动到文本最末尾
moveToEnd(this.$refs.aaa);
//选中框内文本
this.$refs.aaa.select();
}
})
//控制光标移动到末尾的方法
function moveToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
} 2.如果使用了非原生的组件,比如iView的Input,就需要在mounted中加入nextTick <i-input ref="aaa" value="123123"/> var app = new Vue({
el: '#app',
mounted(){
this.$nextTick(() => {
this.$refs.aaa.focus();
//选中所有的文本,即需要找到dom元素
this.$refs.aaa.refs.input.select();
})
}
}) |
vue与react绑定事件写法基本相同,注意一点是,不要绑定匿名函数、箭头函数 mounted(){
window.addEventListener('resize', this.handleLoad)
},
destroyed(){
window.removeEventListener('resize', this.handleLoad)
} 如果vue的组件是keep-live则不能在mounted和destroyed里面写了,改为activated、deactivated componentDidMount() {
window.addEventListener('resize', this.handleLoad);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleLoad);
} |
vue的按需加载路由配置引发的问题场景描述:路由中存在动态参数为查询的文本,页面加载完成之后,input框获取url中的参数并显示出来 vue路由守卫vue的provide然后获取当前inject 选项中的所有key,然后遍历每一个key,拿到每一个key的from属性记作provideKey,provideKey就是上游父级组件提供的源属性,然后开启一个while循环,从当前组件起,不断的向上游父级组件的_provided属性中(父级组件使用provide选项注入数据时会将注入的数据存入自己的实例的_provided属性中)查找,直到查找到源属性的对应的值,将其存入result中,如下: for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const provideKey = inject[key].from
let source = vm
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey]
break
}
source = source.$parent
}
} |
React设置默认props值和类型判定import React, {Component} from 'react'; const defaultProps = { class Test extends Component { Test.defaultProps = defaultProps; // 设置默认props export default Test; |
React中jsx支持if else写法使用babel插件plugin-proposal-do-expressions Redux的本地持久化存储与获取我们创建一个utils.js文件,内容如下,这两个方法分别为本地存储(利用store.subscribe监听)和本地读取数据(用来初始化默认redux的state值),这里简单使用localStorage,如果使用第三方存储,只需要替换即可 /**
* 本地存储常量Key
*/
export const StorageKey = "FILE_MANAGE_STORE"
/**
* 将Redux中store的变化本地持久化
* @param {Object} store
*/
export const subscribeRecord = (store) => { // 将状态记录到 localStorage
store.subscribe(() => {
let data = store.getState().toJS();
data = JSON.stringify(data);
data = encodeURIComponent(data);
if (window.btoa) {
data = btoa(data);
}
console.log(data, 'subscribeRecord');
localStorage.setItem(StorageKey, data);
});
}
/**
* 将持久化数据读取出来
*/
export const lastRecord = (() => { // 上一把的状态
let data = localStorage.getItem(StorageKey);
if (!data) {
return false;
}
try {
if (window.btoa) {
data = atob(data);
}
data = decodeURIComponent(data);
data = JSON.parse(data);
} catch (e) {
if (window.console || window.console.error) {
window.console.error('读取记录错误:', e);
}
return false;
}
console.log(data, 'lastRecordData');
return data;
})(); 在页面初始化的js文件中,给store绑定上subscribe,作为全局监听 import store from './store';
import utils from './utils';
utils.subscribeRecord(store); // 将更新的状态记录到localStorage jsx页面中的逻辑保持不变,即为正常触发store的action即可, import * as actionType from '../../actionType';
import { fromJS, List } from 'immutable';
import utils from '../../../utils';
let defaultState = utils.lastRecord && utils.lastRecord.folderPathLocal && utils.lastRecord.folderPathLocal.length !== 0 ?
List(utils.lastRecord.folderPathLocal) : List([]);
console.log(defaultState.toJS(), 'defaultState', 'folderPathLocal');
export default (state = defaultState, action = {}) => {
switch (action.type) {
case actionType.ADDFOLDERPATHFORLOCAL:
return action.data;
default:
return state;
}
}; 总上所述:
|
自定义元素<my-element content="Custom Element"> Hello</my-element>
<script>
class MyElement extends HTMLElement {//自定义元素
get content() {
return this.getAttribute('content');
}
set content(val) {
this.setAttribute('content', val);
}
}
//原生的window.customElements对象的define方法用来定义 Custom Element。该方法接受两个参数,第一个参数是自定义元素的名字,第二个参数是一个 ES6 的class。
window.customElements.define('my-element', MyElement);
function customTag(tagName, fn) {//Array.from([arguments]);可以将字符串,数组,类数组集合转化为数组
Array
.from(document.getElementsByTagName(tagName))
.forEach(fn);
}
function myElementHandler(element) {
element.textContent = element.content;
}
window.onload = function () {//在页面元素加载完之后,才执行
customTag('my-element', myElementHandler);
}
</script> |
vue的nextick源码: const callbacks = [] // 回调队列
let pending = false // 异步锁
// 执行队列中的每一个回调
function flushCallbacks () {
pending = false // 重置异步锁
// 防止出现nextTick中包含nextTick时出现问题,在执行回调函数队列前,提前复制备份并清空回调函数队列
const copies = callbacks.slice(0)
callbacks.length = 0
// 执行回调函数队列
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
// 将回调函数推入回调队列
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, 'nextTick')
}
} else if (_resolve) {
_resolve(ctx)
}
})
// 如果异步锁未锁上,锁上异步锁,调用异步函数,准备等同步函数执行完后,就开始执行回调函数队列
if (!pending) {
pending = true
if (useMacroTask) {
macroTimerFunc()
} else {
microTimerFunc()
}
}
// 如果没有提供回调,并且支持Promise,返回一个Promise
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}
Watcher.prototype.update = function update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true;
} else if (this.sync) {
this.run();
} else {
queueWatcher(this);
}
};
function queueWatcher (watcher) {
var id = watcher.id;
if (has[id] == null) {
has[id] = true;
if (!flushing) {
queue.push(watcher);
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
var i = queue.length - 1;
while (i > index && queue[i].id > watcher.id) {
i--;
}
queue.splice(i + 1, 0, watcher);
}
// queue the flush
if (!waiting) {
waiting = true;
if (!config.async) {
flushSchedulerQueue();
return
}
nextTick(flushSchedulerQueue);
}
}
}
function flushSchedulerQueue () {
flushing = true;
var watcher, id;
// Sort queue before flush.
// This ensures that:
// 1. Components are updated from parent to child. (because parent is always
// created before the child)
// 2. A component's user watchers are run before its render watcher (because
// user watchers are created before the render watcher)
// 3. If a component is destroyed during a parent component's watcher run,
// its watchers can be skipped.
/*
给queue排序,这样做可以保证:
1.组件更新的顺序是从父组件到子组件的顺序,因为父组件总是比子组件先创建。
2.一个组件的user watchers比render watcher先运行,因为user watchers往往比render watcher更早创建
3.如果一个组件在父组件watcher运行期间被销毁,它的watcher执行将被跳过。
*/
queue.sort(function (a, b) { return a.id - b.id; });
// do not cache length because more watchers might be pushed
// as we run existing watchers
for (index = 0; index < queue.length; index++) {
watcher = queue[index];
if (watcher.before) {
watcher.before();
}
id = watcher.id;
has[id] = null;
watcher.run(); //执行Watcher
// in dev build, check and stop circular updates.
if (has[id] != null) {
circular[id] = (circular[id] || 0) + 1;
//如果超出最大更新次数,就给个提示。
if (circular[id] > MAX_UPDATE_COUNT) {
warn(
'You may have an infinite update loop ' + (
watcher.user
? ("in watcher with expression \"" + (watcher.expression) + "\"")
: "in a component render function."
),
watcher.vm
);
break
}
}
}
// keep copies of post queues before resetting state
var activatedQueue = activatedChildren.slice();
var updatedQueue = queue.slice();
//重置队列状态
resetSchedulerState();
//调用生命周期钩子
callActivatedHooks(activatedQueue);
callUpdatedHooks(updatedQueue);
// devtool hook
/* istanbul ignore if */
if (devtools && config.devtools) {
devtools.emit('flush');
}
} 这里面要注意两点:
vue中静态资源引用(dynamic img src)
参考: vue组件内methods方法是如何绑定this的
https://segmentfault.com/q/1010000007225390 Vue3.0Object.defineProperty -> ProxyObject.defineProperty只能是通过遍历才能进行数据劫持,以及不能劫持数组事件,需要通过数组方法重写,而Proxy则避免了这几个问题 Virtual DOM 重构2.0中Vnode的颗粒度是组件,3.0将颗粒度细化,每次触发更新不再以组件为单位进行遍历,而是动态内容的数量相关 增加了类似于react hook的功能TypeScript |
关于JSX
JSX到JS对象的映射:
JSX 到页面到底经过了这样的过程:
为什么不直接从 JSX 直接渲染构造 DOM 结构,而是要经过中间这么一层呢?
第一:我们拿到一个表示UI的结构对象的时候,不一定渲染到浏览器页面中,比如我可以通过react-canvas渲染到canvas,react-app渲染到原生app中,这个也是react-dom单独抽离,没有和react库在一起的原因。
第二:有了这个对象,当数据变化,需要更新组件的时候,非常方便的比较这个JS对象,而不是直接操作DOM结构,减少浏览器重排,提高性能,这也就是所说的虚拟DOM
The text was updated successfully, but these errors were encountered: