Vue Why asynchronous rendering

Vue Updating DOM Time is executed asynchronously , Just listen for data changes ,Vue A queue will be opened , And buffer all data changes that occur in the same event cycle , If the same watcher Triggered multiple times , Will only be pushed into the queue once , This de duplication of data in buffering avoids unnecessary computation and DOM Operation is very important , then , In the next event loop tick in ,Vue Refresh the queue and execute the actual ( It's gone heavy ) Work ,Vue Try using native... Internally for asynchronous queues Promise.thenMutationObserver and setImmediate, If the execution environment does not support , Will use setTimeout(fn, 0) Instead of .

describe

about Vue Why asynchronous rendering , Simply put, it's to improve performance , Because asynchronous updates are not used , The current component is re rendered every time the data is updated , For performance ,Vue After this round of data update , To update the view asynchronously , for instance , Let's update a value repeatedly within a method .

this.msg = 1;
this.msg = 2;
this.msg = 3;

in fact , What we really want is just the last update , That is to say, the first three times DOM Updates can be omitted , We just need to wait for all the States to be changed before rendering to reduce some performance loss .

The problem with rendering is clear , Rendering only once in the end will definitely cost less performance than rendering after modification , Here we also need to consider the asynchronous update queue related issues , Let's assume that we are now doing the relevant processing so that each update of the data is real only once DOM Rendering , Let's consider the performance optimization of asynchronous update queue .

Let's say this is the synchronous update queue ,this.msg=1, It's about to happen : msg Value update -> Trigger setter -> Trigger Watcher Of update -> Call again render -> Generate a new vdom -> dom-diff -> dom to update , there dom Updating is not rendering ( I.e. layout 、 draw 、 Synthesis and so on ), Instead, update the in memory DOM Tree structure , And then run it this.msg=2, Repeat the above steps , After that 3 Each update triggers the same process , When you start rendering , Abreast of the times DOM It's true that only update completion exists in the tree 3, From here , front 2 Second pair msg The operation of and Vue Internal processing of it is useless operation , It can be optimized .

If it's an asynchronous update queue , It's going to be the following , function this.msg=1, Not immediately , It's going to be about msg Dependent Watcher All in the queue , The queue might look like this [Watcher1, Watcher2...], When running this.msg=2 after , The same will be true for msg Dependent Watcher Save to queue ,Vue The interior will do to re judge , After this operation , It can be assumed that the queue data has not changed , The first 3 The next update is also the above process , Of course , You can't just be right msg There are operations , You may also have an action on another property in the component , such as this.otherMsg=othermessage, The same will be true of otherMsg Dependent Watcher Add to asynchronous update queue , Because there's repetitive judgment , This Watcher Only once in the queue , At the end of this asynchronous task execution , Will enter the next task execution process , It's actually traversing every one of the asynchronous update queues Watcher, Trigger it update, And then make a new call render -> new vdom -> dom-diff -> dom Update and so on , But compared to the synchronous update queue , No matter how many times msg, Vue Internally, there is only one re call to the real update process , therefore , For asynchronous update queues, it doesn't save rendering costs , It saves Vue Internal calculation and DOM The cost of tree operations , Either way , Rendering really only once .

Besides , The actual use inside the component VirtualDOM Rendering , in other words , Inside the component, it doesn't care which state has changed , It only needs to calculate once to know which nodes need to be updated , in other words , If changed N Status , In fact, you only need to send a signal to DOM Update to the latest , If we update multiple values .

this.msg = 1;
this.age = 2;
this.name = 3;

Here we modify three states three times , But in fact Vue It will only render once , because VIrtualDOM It only takes one time for the entire component to be DOM Update to the latest , It doesn't care which specific state the update signal is sent from .

And to do that , We need to postpone rendering until all States are modified , To do this, you just need to postpone rendering until the end of this event loop or the next one , in other words , Just at the end of this cycle of events , After all the previous statements to update the status are executed , Performs a rendering operation , It can ignore the previous syntax of various update States , No matter how many statements are written to update the status , Just one final rendering .

Postponing rendering to the end of this event cycle is much faster than postponing rendering to the next one , therefore Vue Priority is given to postponing rendering operations to the end of the current event loop , If the execution environment is not supported, it will be degraded to the next round ,Vue The mechanism of change detection (setter) It will send out the signal of rendering every time the state changes , but Vue After receiving the signal, it will check whether the task already exists in the queue , Make sure there's no repetition in the queue , If the queue does not exist, add the rendering operation to the queue , After that, all rendering operations in the queue are delayed and the queue is cleared asynchronously , When the state is modified repeatedly in the same event cycle , It doesn't add the same rendering operation to the queue over and over again , So we're using Vue when , Update after modifying the status DOM It's all asynchronous .

When the data changes, it will call notify Method , take watcher Traverse , call update Method notice watcher updated , Now watcher Not immediately , stay update Will call queueWatcher Methods will watcher Put it in a queue , stay queueWatcher Will be based on watcher To carry out the de duplication of , If multiple attributes depend on one watcher, If there is no such watcher It will watcher Add to queue , And then it will be in $nextTick Method to the execution queue flushSchedulerQueue Method ( This method will trigger the execution of all callbacks in the buffer queue ), And then $nextTick Method to join $nextTick Method ,flushSchedulerQueue In the beginning, a before Methods , In fact, that is beforeUpdate, then watcher.run() It's just beginning to really execute watcher, After executing the page, the rendering is complete , When the update is complete, it calls updated hook .

$nextTick

In the above, we talked about Vue Why asynchronous rendering , If we have a need at this time , You need to get the page's DOM Elements , And because rendering is asynchronous , We can't get this value synchronously in the defined method , So there was vm.$nextTick Method ,Vue in $nextTick Method to delay the callback until the next time DOM After the update loop , That is, next time DOM A delayed callback is executed after the update loop is completed , Use this method immediately after modifying the data , Can get the updated DOM. In short, when the data is updated , stay DOM After rendering in , Execute callback function .

Let's show it with a simple example $nextTick The role of methods , The first thing you need to know is Vue Updating DOM Time is executed asynchronously , That is to say, when updating the data, it will not block the execution of the code , Until the end of code execution in the execution stack , Start executing the asynchronous task queue code , So when the data is updated , Components don't render immediately , At this point in the acquisition of DOM The value obtained after the structure is still the old value , And in the $nextTick The callback function set in method will be executed after the component rendering is completed , obtain DOM The value obtained after the structure is the new value .

<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'Vue'
},
template:`
<div>
<div ref="msgElement">{{msg}}</div>
<button @click="updateMsg">updateMsg</button>
</div>
`,
methods:{
updateMsg: function(){
this.msg = "Update";
console.log("DOM Not updated :", this.$refs.msgElement.innerHTML)
this.$nextTick(() => {
console.log("DOM Updated :", this.$refs.msgElement.innerHTML)
})
}
}, })
</script>
</html>

Asynchronous mechanism

The official document says ,Vue Updating DOM Time is executed asynchronously , Just listen for data changes ,Vue A queue will be opened , And buffer all data changes that occur in the same event cycle , If the same watcher Triggered multiple times , Will only be pushed into the queue once . This de duplication of data in buffering avoids unnecessary computation and DOM Operation is very important . then , In the next event loop tick in ,Vue Refresh the queue and perform the actual work .Vue Try using native... Internally for asynchronous queues Promise.thenMutationObserver and setImmediate, If the execution environment does not support , Will use setTimeout(fn, 0) Instead of .

Js It's single threaded , It introduces synchronous blocking and asynchronous non blocking execution modes , stay Js In asynchronous mode, a Event Loop,Event Loop It's an execution model , There are different implementations in different places , The browser and NodeJS Based on different technologies, we have realized their own Event Loop. Browser's Event Loop Is in HTML5 It is clearly defined in the specification of ,NodeJS Of Event Loop Is based on libuv Realized .

In the browser Event Loop By the execution stack Execution Stack、 Background thread Background Threads、 Macro queue Macrotask Queue、 Micro queue Microtask Queue form .

  • The execution stack is the data structure that executes synchronization tasks in the main thread , Function calls form a stack of frames .
  • Background thread is the browser implementation for setTimeoutsetIntervalXMLHttpRequest And so on .
  • Macro queue , Callbacks of some asynchronous tasks will enter the macro queue in turn , Waiting for subsequent calls , Include setTimeoutsetIntervalsetImmediate(Node)requestAnimationFrameUI renderingI/O Wait for the operation .
  • Micro queue , Callbacks of other asynchronous tasks will enter the micro queue in turn , Waiting for subsequent calls , Include Promiseprocess.nextTick(Node)Object.observeMutationObserver Wait for the operation .

When Js Execution time , Proceed as follows :

  1. First, the code in the execution stack is executed synchronously , Add the asynchronous tasks in the code to the background thread .
  2. After the synchronization code in the execution stack is executed , Perform stack clear , And start scanning the micro queue .
  3. Take out the first task of the micro team , Put it into the execution stack to execute , At this time, the micro queue is out of the queue .
  4. When the execution stack is finished , Continue to dequeue the micro Queue task and execute , Until all the micro queue tasks are completed .
  5. After the last micro Queue task is out of the queue and enters the execution stack, the task in the micro queue is empty , When the stack task is finished , Start scanning. The micro queue is empty , Continue scanning macro queue tasks , Acer team lists teams , Put it into the execution stack to execute , After the execution, continue to scan. If the micro queue is empty, scan the macro queue , Get out of the team .
  6. To and fro ....

example

// Step 1
console.log(1); // Step 2
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3);
});
}, 0); // Step 3
new Promise((resolve, reject) => {
console.log(4);
resolve();
}).then(() => {
console.log(5);
}) // Step 4
setTimeout(() => {
console.log(6);
}, 0); // Step 5
console.log(7); // Step N
// ... // Result
/*
1
4
7
5
2
3
6
*/
Step 1
// Execution stack console
// Micro queue []
// Macro queue []
console.log(1); // 1
Step 2
// Execution stack setTimeout
// Micro queue []
// Macro queue [setTimeout1]
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3);
});
}, 0);
Step 3
// Execution stack Promise
// Micro queue [then1]
// Macro queue [setTimeout1]
new Promise((resolve, reject) => {
console.log(4); // 4 // Promise It's a function object , Here is synchronous execution // Execution stack Promise console
resolve();
}).then(() => {
console.log(5);
})
Step 4
// Execution stack setTimeout
// Micro queue [then1]
// Macro queue [setTimeout1 setTimeout2]
setTimeout(() => {
console.log(6);
}, 0);
Step 5
// Execution stack console
// Micro queue [then1]
// Macro queue [setTimeout1 setTimeout2]
console.log(7); // 7
Step 6
// Execution stack then1
// Micro queue []
// Macro queue [setTimeout1 setTimeout2]
console.log(5); // 5
Step 7
// Execution stack setTimeout1
// Micro queue [then2]
// Macro queue [setTimeout2]
console.log(2); // 2
Promise.resolve().then(() => {
console.log(3);
});
Step 8
// Execution stack then2
// Micro queue []
// Macro queue [setTimeout2]
console.log(3); // 3
Step 9
// Execution stack setTimeout2
// Micro queue []
// Macro queue []
console.log(6); // 6

analysis

After understanding the execution queue of asynchronous tasks , Back in the middle $nextTick Method , When user data is updated ,Vue A buffer queue will be maintained , For all the updated data, the component rendering and DOM The operation is added to the buffer queue after certain policy processing , And then it will be in $nextTick Method to the execution queue flushSchedulerQueue Method ( This method will trigger the execution of all callbacks in the buffer queue ), And then $nextTick Method to join $nextTick Method , When the execution queue of asynchronous mount is triggered, it will be executed first flushSchedulerQueue Method to handle DOM The task of rendering , Then go ahead and do it $nextTick The task of method construction , This can be achieved in $nextTick Method to get the rendered DOM structure . In the process of testing, we found a very interesting phenomenon , In the above example, add two buttons , Click on updateMsg The result of the button is 3 2 1, Click on updateMsgTest The result of the button is 2 3 1.

<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'Vue'
},
template:`
<div>
<div ref="msgElement">{{msg}}</div>
<button @click="updateMsg">updateMsg</button>
<button @click="updateMsgTest">updateMsgTest</button>
</div>
`,
methods:{
updateMsg: function(){
this.msg = "Update";
setTimeout(() => console.log(1))
Promise.resolve().then(() => console.log(2))
this.$nextTick(() => {
console.log(3)
})
},
updateMsgTest: function(){
setTimeout(() => console.log(1))
Promise.resolve().then(() => console.log(2))
this.$nextTick(() => {
console.log(3)
})
}
}, })
</script>
</html>

Let's assume that in the running environment Promise Objects are fully supported , So use setTimeout It's the macro queue that runs at the end, and there's no objection to that , But use $nextTick Methods and self-defined Promise There is a problem with the order of execution of instances , Although they are all micro queue tasks , But in Vue The execution order may be different due to the implementation in , First, take a look at $nextTick Method source code , Notes have been added in key areas , Please note that this is Vue2.4.2 Version of the source , In the later period $nextTick Methods may change .

/**
* Defer a task to execute it asynchronously.
*/
var nextTick = (function () {
// Closure Internal variables
var callbacks = []; // Perform the queue
var pending = false; // identification , It is used to judge whether it is the first time to join in an event cycle , The queue mount of asynchronous execution is triggered only when joining for the first time
var timerFunc; // How to mount the asynchronous execution queue , It is assumed that Promise It's fully supported function nextTickHandler () { // Asynchronously mounted execution tasks , When triggered, it is ready to start performing asynchronous tasks
pending = false; // Logo set false
var copies = callbacks.slice(0); // Create copy
callbacks.length = 0; // Execution queue is empty
for (var i = 0; i < copies.length; i++) {
copies[i](); // perform
}
} // the nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
// MutationObserver has wider support, however it is seriously bugged in
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore if */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
var p = Promise.resolve();
var logError = function (err) { console.error(err); };
timerFunc = function () {
p.then(nextTickHandler).catch(logError); // Mount asynchronous task queue
// in problematic UIWebViews, Promise.then doesn't completely break, but
// it can get stuck in a weird state where callbacks are pushed into the
// microtask queue but the queue isn't being flushed, until the browser
// needs to do some other work, e.g. handle a timer. Therefore we can
// "force" the microtask queue to be flushed by adding an empty timer.
if (isIOS) { setTimeout(noop); }
};
} else if (typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
// PhantomJS and iOS 7.x
MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
// use MutationObserver where native Promise is not available,
// e.g. PhantomJS IE11, iOS7, Android 4.4
var counter = 1;
var observer = new MutationObserver(nextTickHandler);
var textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true
});
timerFunc = function () {
counter = (counter + 1) % 2;
textNode.data = String(counter);
};
} else {
// fallback to setTimeout
/* istanbul ignore next */
timerFunc = function () {
setTimeout(nextTickHandler, 0);
};
} return function queueNextTick (cb, ctx) { // nextTick Methods the methods that are actually exported
var _resolve;
callbacks.push(function () { // Add to execution queue And add exception handling
if (cb) {
try {
cb.call(ctx);
} catch (e) {
handleError(e, ctx, 'nextTick');
}
} else if (_resolve) {
_resolve(ctx);
}
});
// Determine whether to join for the first time in the current event cycle , If it is added for the first time, set the mark as true And implement timerFunc Function to mount the execution queue to Promise
// This flag is set to... When the task in the execution queue is about to be executed false And create a copy of the execution queue to run the tasks in the execution queue , See nextTickHandler Implementation of function
// Set the flag in the current event loop true And mount , Then call... Again nextTick Method just adds the task to the execution queue , Until the mounted asynchronous task triggers , Set the logo as false And then execute the task , Call again nextTick Methods are executed in the same way, and then repeatedly
if (!pending) {
pending = true;
timerFunc();
}
if (!cb && typeof Promise !== 'undefined') {
return new Promise(function (resolve, reject) {
_resolve = resolve;
})
}
}
})();

Back to the question just raised , Updating DOM Operation will trigger first $nextTick Method's callback , The key to solve this problem is who mounts the asynchronous task to Promise On the object .

First of all, update the data updateMsg Button trigger method debug, The breakpoint is set at Vue.js Of 715 That's ok , Version is 2.4.2, When you look at the call stack and the parameters passed in, you can see the first execution $nextTick Method is actually called due to data update nextTick(flushSchedulerQueue); sentence , That is to say, in the implementation of this.msg = "Update"; It's already triggered the first time $nextTick Method , At this time in $nextTick The task queue in method will first flushSchedulerQueue Method to join the queue and mount $nextTick Method execution queue to Promise On the object , And then it's self defining Promise.resolve().then(() => console.log(2)) Statement mount , When executing a task in the micro task queue , The first mount to Promise The task of , At this point, the task is to run the execution queue , There are two methods in this queue , First it will run flushSchedulerQueue Method to trigger the DOM Rendering operations , And then execute console.log(3), And then perform the task of the second micro queue, which is () => console.log(2), At this time, the micro task queue is cleared , Then go to the macro task queue to execute console.log(1).

Next, for those without data update updateMsgTest Button trigger method debug, The breakpoint is set in the same position , There is no data update at this time , So the first trigger $nextTick Method is a self-defined callback function , So at this time $nextTick The execution queue of the method will be mounted to Promise On the object , Obviously, the self-defined output before that 2 Of Promise The callback has been mounted , Then the execution process of the button binding method is to execute first console.log(2), And then execute $nextTick Method closure execution queue , There is only one callback function in the execution queue console.log(3), At this time, the micro task queue is cleared , Then go to the macro task queue to execute console.log(1).

In short, who will mount it first Promise Object problem , Calling $nextTick Method will mount the execution queue maintained inside its closure to Promise object , When the data is updated Vue Inside, it's going to be done first $nextTick Method , Then the execution queue is mounted to Promise On the object , Actually, I understand Js Of Event Loop After the model , Think of data update as a $nextTick Method call , And understand $nextTick Method executes all pushed callbacks at one time , Then you can understand the problem of execution order , Here's one about $nextTick Methods of minimization DEMO.

var nextTick = (function(){
var pending = false;
const callback = [];
var p = Promise.resolve(); var handler = function(){
pending = true;
callback.forEach(fn => fn());
} var timerFunc = function(){
p.then(handler);
} return function queueNextTick(fn){
callback.push(() => fn());
if(!pending){
pending = true;
timerFunc();
}
} })(); (function(){
nextTick(() => console.log(" Trigger DOM How to render the queue ")); // notes / uncomment To see the effect
setTimeout(() => console.log(1))
Promise.resolve().then(() => console.log(2))
nextTick(() => {
console.log(3)
})
})();

A daily topic

https://github.com/WindrunnerMax/EveryDay

Reference resources

https://zhuanlan.zhihu.com/p/29631893
https://github.com/berwin/Blog/issues/22
https://juejin.cn/post/6899822303022956552
https://segmentfault.com/a/1190000015698196
https://cn.vuejs.org/v2/guide/reactivity.html
https://blog.csdn.net/weixin_46396187/article/details/107462329

Vue Why asynchronous rendering

  1. vue Asynchronous rendering

    <!DOCTYPE html> <html> <head> <title> hello world vue </title> <met ...

  2. Vue.js Server side rendering business entry practice

    author : Weiwei ( Hujiang front end Development Engineer ) This article is original. , Please indicate the author and source of reprint . background lately , As usual, the product students smile and present the requirement documents , Even if the heart refused , The body is honest . Take over the demand , Fortunately, the demand is not complicated , Simple idea after ...

  3. Use asynchrony to realize reconnecting server or restarting service C# Get the properties of the class in SignalR2 Simple data Kanban Demo C# Calling generic classes dynamically 、 Generic methods asp .net core Get raw request. Start at one and separate the front and back ends [.NetCore Irregular update ] 38 ║ Automatically initialize the database

    Use asynchrony to realize reconnecting server or restarting service Turn on asynchronous listening , It will not block the main thread , Always detect reconnection service after service abnormally disconnected , After successfully connecting to the service, notify each registered client ! #region Detect disconnection and reconnection OPC service ...

  4. From the parent-child component of mounted The synchronous execution of the hook and the asynchronous rendering of the page nextTick Usage of

    Recent review vue I met a very strange problem when I was young , Let's look directly at the examples : <div id="app"> <child ref="child">& ...

  5. Vue v-for Nested data rendering problems

    Vue v-for Nested data rendering problems Problem description : Because when we get the commodity subcategories , At the same time, we need to get the goods under the subcategory , Then multi layer list rendering can only be the first layer easy to use Question why : vue When dealing with multi-layer rendering , We can't just use the equal sign to assign ...

  6. WPF Use SharpDx Asynchronous rendering

    This article tells you how to pass SharpDx Render asynchronously , But because in WPF It is necessary to use D3DImage Draw out , So rendering is just drawing pictures , The final display still needs WPF Rendering in his own main thread This article is a series , Greek ...

  7. document.compatMode( Determine the rendering mode adopted by the current browser )

    Reprinted from :http://www.cnblogs.com/fullhouse/archive/2012/01/17/2324706.html IE The rendering of the box model is in Standards Mode and Quirk ...

  8. ASP.NET Core And Vue.js Server rendering

    http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/ The original author :Mihály Gyöngyösi translator :oop ...

  9. understand Vue Medium Render Rendering function

    understand Vue Medium Render Rendering function VUE In general use template To create HTML, And then sometimes , We need to use javascript To create html, We need to use render function . For example, I want to achieve ...

  10. RDIFramework.NET ━ .NET Framework of rapid information system development V3.2-&gt; newly added “ Administrative region management ”, At the same time, a large number of trees are loaded asynchronously

    The administrative area : It's called administrative district for short , It is a regional division implemented by the state for hierarchical management . China's current administrative divisions follow the following principles :1. The country is divided into provinces . Autonomous region . Municipalities directly under the central government :2. province . Autonomy is divided into autonomous states . county . autonomous county . City :3. Autonomous Prefecture is divided into counties . autonomous county . City :4. ...

Random recommendation

  1. Linux The next server development process and related tools (C++)

    After graduating last year and coming to the company , Be a new person , Found a lot of things without documentation , All kinds of tools and addresses are handed down by word of mouth , And most of the time, I don't know which tools can be used , So I wanted to record what I was exposed to , Provide reference for the latecomers , It's like a road ...

  2. C# Must read books

    C# in Depth: It's about C# Things that are .CLR via C#: It's about runtime things .Framework Design Guideline: It's about how to design a class library to work with .NET all blend into one harmonious whole .——“ Zhao Sanben ...

  3. 413 Request Entity Too Large

    Do small video upload , The result interface always returns 500, Server side tracking , I can't get in at all , Check again , What the server returns is 413, It's just APP The underlying interface will not be all 200 All the return packages are converted into 500 了 , Problem location . With the error code , With a description , word ...

  4. Deepen understanding mysql Data transmission coding principle

    One . Basic concepts ( Here quote http://www.laruence.com/2008/01/05/12.html) 1. Given a series of characters , Assign a number to each character , Use numeric values to represent the corresponding characters , This number is the number of characters ...

  5. Maven json Package can't find a solution

    stay Maven Central warehouse found Maven Of jar <dependency> <groupId>net.sf.json-lib</groupId> <artifact ...

  6. Python--day10( function ( Use 、 classification 、 Return value ))

    1.  function 1.  function : A block of code that performs a specific function , As a whole , Give it a specific name , The name stands for this function In reality : Many problems need to be dealt with by some tools => Tools can be produced in advance and named => through ...

  7. nginx Shield a ip The interview of

    Suppose we want to ban access nginx The most frequent ip Visit our website We can find out that first ip Most visits awk '{print $1}' nginx.access.log |sort |uniq -c|sort ...

  8. Tortoise svn The reason why we can't pull the code

    Because an account can only login on one client , With the same account number , There is bound to be a failure , Tips unable connect to url resolvent : Just make it clear

  9. PythonWeb Development tutorial ( One ), What needs to be prepared before development

    What is? web Development , In fact, it is to develop a website . What kind of knowledge do you need to develop a website 1.python Basics , Because with python Developed , therefore python I want to know , At least you have to know how to judge , loop , function , Like this knowledge : 2 ...

  10. 《JAVA With the model 》 Reference to

    1. Books <JHead First Design patterns ( Chinese version )> <JAVA With the model > < Big talk design patterns > 2. Connection address http://blog.csdn.net/jason0 ...