1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>vue 3</title>
6 <style>
7 .message-container {
8 margin: 5px 0;
9 border: 1px dashed lightcoral;
10 text-align: left;
11 }
12
13 .message-container div {
14 padding-left: 10px;
15 }
16 </style>
17 </head>
18 <body>
19 <div id="app">
20 <message name="gua"></message>
21 <message name="xiao gua"></message>
22 <!-- <button v-on:click="handleToggleTimer">开关 timer</button> -->
23 <!-- v-on:click 可以缩写成 @click, 在 vue 里面这样的缩写很常见, 多写写就会记下来 -->
24 <button @click="handleToggleTimer">开关 timer</button>
25 <!-- v-if 表示如果 showTimer 的值为 true, 那么就会渲染 timer 组件 -->
26 <!-- 组件会在后面描述 -->
27 <div v-if="showTimer">
28 <timer></timer>
29 </div>
30 <markdown-editor></markdown-editor>
31 </div>
32
33 <!-- 引入 vue -->
34 <!-- 注意, 工作中并不是这样引入 vue 的, 我们先用最简单的方式引入, 之后会有复杂例子 -->
35 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
36 <script src="https://unpkg.com/marked@0.3.6"></script>
37 <script>
38 const log = console.log.bind(console)
39
40 // 使用 Vue.component 可以定义一个组件, 第一个参数是组件的名称
41 // 定义组件之后可以直接在 html 里面使用
42 Vue.component('message', {
43 // props 用来指定组件可以接收哪些属性
44 // 在 html 中使用组件的时候可以直接通过 name="xxx" 传递值
45 // 传递的值可以在组件内部使用
46 // props 类似 react 组件的 props
47 props: ['name'],
48 // template 的值是一个 html 格式的字符串
49 // 这个字符串会替换掉组件, 也就是 <message></message> 组件的内容会换成 template 的值
50 // 注意 template 里面的变量可以从 props 中获取
51 template: `
52 <div class="message-container">
53 <div>Hello {{ name }}</div>
54 <div>大写 {{ name.toUpperCase() }}</div>
55 </div>
56 `,
57 })
58
59 Vue.component('timer', {
60 // 组件中依然可以使用 data 这个属性, 但是 data 的值不能是一个对象
61 // 必须是一个函数, 然后在函数内部返回一个对象, 用来表示组件内部的数据
62 // 依然类似 react 组件的 state
63 data: function() {
64 return {
65 secondsElapsed: 0,
66 }
67 },
68 template: `
69 <div>
70 启动时间: {{ secondsElapsed }}
71 </div>
72 `,
73 methods: {
74 tick: function() {
75 // 每次调用 tick 方法都会让 secondsElapsed 增加 1
76 this.secondsElapsed += 1
77 }
78 },
79 // created 是实例创建完成后会被调用的方法
80 // 类似 react 中的 componentDidMount
81 created: function() {
82 console.log('定时器组件 did mount')
83 this.interval = setInterval(() => this.tick(), 1000)
84 },
85 // destroyed 表示实例销毁后会被调用的方法
86 // 类似 react 中的 componentWillUnmount
87 destroyed: function() {
88 console.log('定时器组件 will unmount')
89 clearInterval(this.interval)
90 },
91 })
92
93 Vue.component('markdown-editor', {
94 data: function() {
95 return {
96 mdString: '输入 *markdown 语法* 就能看到效果',
97 }
98 },
99 // template 中使用了 v-html 这个指令, 是用来设置元素的 innerHTML 属性的
100 // 每次都会将 getRawMarkup 函数的返回值设置为 innerHTML 的值
101 template: `
102 <div className="MarkdownEditor">
103 <h1>markdown 编辑器</h1>
104 <h3>原始 md 文本</h3>
105 <textarea v-model="mdString"></textarea>
106 <h3>结果预览</h3>
107 <div class="content" v-html="getRawMarkup()"></div>
108 </div>
109 `,
110 methods: {
111 getRawMarkup: function() {
112 // 因为 textarea 使用了 v-model 指令
113 // 所以当 mdString 发生变化的时候, getRawMarkup 方法中可以获取用户输入的 mdString 值
114 // marked 方法用来把一个 markdown 字符串转成 html 格式的字符串入
115 return marked(this.mdString)
116 },
117 },
118 })
119
120 let app = new Vue({
121 el: '#app',
122 data: {
123 showTimer: true,
124 },
125 methods: {
126 // 切换 showTimer 属性的值
127 handleToggleTimer: function() {
128 this.showTimer = !this.showTimer
129 }
130 }
131 })
132 </script>
133 </body>
134 </html>