8000 异步组件1文档 · gitbu/learn-vue@a340eba · GitHub
[go: up one dir, main page]

Skip to content

Commit a340eba

Browse files
author
buaiping
committed
异步组件1文档
1 parent 1ebb355 commit a340eba

File tree

6 files changed

+595
-0
lines changed

6 files changed

+595
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# compileToFunctions和
2+
3+
```js
4+
/* @flow */
5+
6+
import { baseOptions } from './options'
7+
import { createCompiler } from 'compiler/index'
8+
9+
const { compile, compileToFunctions } = createCompiler(baseOptions)
10+
11+
export { compile, compileToFunctions }
12+
13+
```
14+
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# createCompileToFunctionFn
2+
3+
```js
4+
/* @flow */
5+
6+
import { noop, extend } from 'shared/util'
7+
import { warn as baseWarn, tip } from 'core/util/debug'
8+
import { generateCodeFrame } from './codeframe'
9+
10+
type CompiledFunctionResult = {
11+
render: Function;
12+
staticRenderFns: Array<Function>;
13+
};
14+
// 这里的new Function(code)就是用把模板字符串转换成函数
15+
function createFunction (code, errors) {
16+
try {
17+
return new Function(code)
18+
} catch (err) {
19+
errors.push({ err, code })
20+
return noop
21+
}
22+
}
23+
24+
export function createCompileToFunctionFn (compile: Function): Function {
25+
const cache = Object.create(null)
26+
27+
return function compileToFunctions (
28+
template: string,
29+
options?: CompilerOptions,
30+
vm?: Component
31+
): CompiledFunctionResult {
32+
options = extend({}, options)
33+
const warn = options.warn || baseWarn
34+
delete options.warn
35+
36+
/* istanbul ignore if */
37+
if (process.env.NODE_ENV !== 'production') {
38+
// detect possible CSP restriction
39+
try {
40+
new Function('return 1')
41+
} catch (e) {
42+
if (e.toString().match(/unsafe-eval|CSP/)) {
43+
warn(
44+
'It seems you are using the standalone build of Vue.js in an ' +
45+
'environment with Content Security Policy that prohibits unsafe-eval. ' +
46+
'The template compiler cannot work in this environment. Consider ' +
47+
'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
48+
'templates into render functions.'
49+
)
50+
}
51+
}
52+
}
53+
54+
// check cache
55+
const key = options.delimiters
56+
? String(options.delimiters) + template
57+
: template
58+
if (cache[key]) {
59+
return cache[key]
60+
}
61+
62+
// compile
63+
const compiled = compile(template, options)
64+
65+
// check compilation errors/tips
66+
if (process.env.NODE_ENV !== 'production') {
67+
if (compiled.errors && compiled.errors.length) {
68+
if (options.outputSourceRange) {
69+
compiled.errors.forEach(e => {
70+
warn(
71+
`Error compiling template:\n\n${e.msg}\n\n` +
72+
generateCodeFrame(template, e.start, e.end),
73+
vm
74+
)
75+
})
76+
} else {
77+
warn(
78+
`Error compiling template:\n\n${template}\n\n` +
79+
compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
80+
vm
81+
)
82+
}
83+
}
84+
if (compiled.tips && compiled.tips.length) {
85+
if (options.outputSourceRange) {
86+
compiled.tips.forEach(e => tip(e.msg, vm))
87+
} else {
88+
compiled.tips.forEach(msg => tip(msg, vm))
89+
}
90+
}
91+
}
92+
93+
// turn code into functions
94+
const res = {}
95+
const fnGenErrors = []
96+
res.render = createFunction(compiled.render, fnGenErrors)
97+
res.staticRenderFns = compiled.staticRenderFns.map(code => {
98+
return createFunction(code, fnGenErrors)
99+
})
100+
101+
// check function generation errors.
102+
// this should only happen if there is a bug in the compiler itself.
103+
// mostly for codegen development use
104+
/* istanbul ignore if */
105+
if (process.env.NODE_ENV !== 'production') {
106+
if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
107+
warn(
108+
`Failed to generate render function:\n\n` +
109+
fnGenErrors.map(({ err, code }) => `${err.toString()} in\n\n${code}\n`).join('\n'),
110+
vm
111+
)
112+
}
113+
}
114+
115+
return (cache[key] = res)
116+
}
117+
}
118+
119+
```
120+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# createCompiler
2+
3+
```js
4+
export const createCompiler = createCompilerCreator(function baseCompile (
5+
template: string,
6+
options: CompilerOptions
7+
): CompiledResult {
8+
const ast = parse(template.trim(), options)
9+
if (options.optimize !== false) {
10+
optimize(ast, options)
11+
}
12+
const code = generate(ast, options)
13+
return {
14+
ast,
15+
render: code.render,
16+
staticRenderFns: code.staticRenderFns
17+
}
18+
})
19+
```
20+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# createCompilerCreator
2+
3+
```js
4+
/* @flow */
5+
6+
import { extend } from 'shared/util'
7+
import { detectErrors } from './error-detector'
8+
import { createCompileToFunctionFn } from './to-function'
9+
10+
export function createCompilerCreator (baseCompile: Function): Function {
11+
return function createCompiler (baseOptions: CompilerOptions) {
12+
function compile (
13+
template: string,
14+
options?: CompilerOptions
15+
): CompiledResult {
16+
const finalOptions = Object.create(baseOptions)
17+
const errors = []
18+
const tips = []
19+
20+
let warn = (msg, range, tip) => {
21+
(tip ? tips : errors).push(msg)
22+
}
23+
24+
if (options) {
25+
if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {
26+
// $flow-disable-line
27 6D38 +
const leadingSpaceLength = template.match(/^\s*/)[0].length
28+
29+
warn = (msg, range, tip) => {
30+
const data: WarningMessage = { msg }
31+
if (range) {
32+
if (range.start != null) {
33+
data.start = range.start + leadingSpaceLength
34+
}
35+
if (range.end != null) {
36+
data.end = range.end + leadingSpaceLength
37+
}
38+
}
39+
(tip ? tips : errors).push(data)
40+
}
41+
}
42+
// merge custom modules
43+
if (options.modules) {
44+
finalOptions.modules =
45+
(baseOptions.modules || []).concat(options.modules)
46+
}
47+
// merge custom directives
48+
if (options.directives) {
49+
finalOptions.directives = extend(
50+
Object.create(baseOptions.directives || null),
51+
options.directives
52+
)
53+
}
54+
// copy other options
55+
for (const key in options) {
56+
if (key !== 'modules' && key !== 'directives') {
57+
finalOptions[key] = options[key]
58+
}
59+
}
60+
}
61+
62+
finalOptions.warn = warn
63+
64+
const compiled = baseCompile(template.trim(), finalOptions)
65+
if (process.env.NODE_ENV !== 'production') {
66+
detectErrors(compiled.ast, warn)
67+
}
68+
compiled.errors = errors
69+
compiled.tips = tips
70+
return compiled
71+
}
72+
73+
return {
74+
compile,
75+
compileToFunctions: createCompileToFunctionFn(compile)
76+
}
77+
}
78+
}
79+
80+
```
81+

docs/vue2/compile/调用编译.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# 调用编译
2+
3+
*src/platforms/web/entry-runtime-with-compiler.js*
4+
5+
```js{4}
6+
/* @flow */
7+
8+
import config from 'core/config'
9+
import { warn, cached } from 'core/util/index'
10+
import { mark, measure } from 'core/util/perf'
11+
12+
import Vue from './runtime/index'
13+
import { query } from './util/index'
14+
import { compileToFunctions } from './compiler/index'
15+
import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat'
16+
17+
const idToTemplate = cached(id => {
18+
const el = query(id)
19+
return el && el.innerHTML
20+
})
21+
22+
const mount = Vue.prototype.$mount
23+
Vue.prototype.$mount = function (
24+
el?: string | Element,
25+
hydrating?: boolean
26+
): Component {
27+
el = el && query(el)
28+
29+
/* istanbul ignore if */
30+
if (el === document.body || el === document.documentElement) {
31+
process.env.NODE_ENV !== 'production' && warn(
32+
`Do not mount Vue to <html> or <body> - mount to normal elements instead.`
33+
)
34+
return this
35+
}
36+
37+
const options = this.$options
38+
// resolve template/el and convert to render function
39+
if (!options.render) {
40+
let template = options.template
41+
if (template) {
42+
if (typeof template === 'string') {
43+
if (template.charAt(0) === '#') {
44+
template = idToTemplate(template)
45+
/* istanbul ignore if */
46+
if (process.env.NODE_ENV !== 'production' && !template) {
47+
warn(
48+
`Template element not found or is empty: ${options.template}`,
49+
this
50+
)
51+
}
52+
}
53+
} else if (template.nodeType) {
54+
template = template.innerHTML
55+
} else {
56+
if (process.env.NODE_ENV !== 'production') {
57+
warn('invalid template option:' + template, this)
58+
}
59+
return this
60+
}
61+
} else if (el) {
62+
template = getOuterHTML(el)
63+
}
64+
if (template) {
65+
/* istanbul ignore if */
66+
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
67+
mark('compile')
68+
}
69+
70+
const { render, staticRenderFns } = compileToFunctions(template, {
71+
outputSourceRange: process.env.NODE_ENV !== 'production',
72+
shouldDecodeNewlines,
73+
shouldDecodeNewlinesForHref,
74+
delimiters: options.delimiters,
75+
comments: options.comments
76+
}, this)
77+
options.render = render
78+
options.staticRenderFns = staticRenderFns
79+
80+
/* istanbul ignore if */
81+
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
82+
mark('compile end')
83+
measure(`vue ${this._name} compile`, 'compile', 'compile end')
84+
}
85+
}
86+
}
87+
return mount.call(this, el, hydrating)
88+
}
89+
90+
/**
91+
* Get outerHTML of elements, taking care
92+
* of SVG elements in IE as well.
93+
*/
94+
function getOuterHTML (el: Element): string {
95+
if (el.outerHTML) {
96+
return el.outerHTML
97+
} else {
98+
const container = document.createElement('div')
99+
container.appendChild(el.cloneNode(true))
100+
return container.innerHTML
101+
}
102+
}
103+
104+
Vue.compile = compileToFunctions
105+
106+
export default Vue
107+
108+
```
109+

0 commit comments

Comments
 (0)
0