Vue 语法初探
1. 用 vue 编写定时器
最原始形态,把 app 挂载到 id 为 root 的元素上,然后 template 展示相关的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Vue 的 CDN -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
template: `<div>hello world</div>`,
}).mount("#root")
</script>
</html>
除了 template 属性外,还有 data 用于存储数据,以及生命周期函数在特定的时机触发相应的函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Vue 的 CDN -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 在 id 为 root 的元素上使用 vue
const app = Vue.createApp({
// data 存储变量
data() {
return {
content: 1,
}
},
// 生命周期函数,在挂载完成时自动触发
mounted() {
// 定时器,每秒 content 加一
setTimeout(() => { this.content += 1 }, 1000)
},
// 里边的模板作为展示内容
// 双花括号代表 js 表达式,所以会被 data 里的 content 替换
template: "<div>{{ content }}</div>"
}).mount("#root")
</script>
</html>
双括号是插值表达式,里边可以放 js 表达式。
如果标签里的属性需要和数据绑定,需要用 v-bind 指令。
this.content 可以直接操作 data 里面的 content。this.content 等价于 this.$data.content。当 content 发生变化,展示的内容也会跟着发生变化,和以前编写 DOM 的方法完全不同。
2. 反转字符串和内容隐藏功能
2.1 反转字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Vue 的 CDN -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
content: "hello world"
}
},
// 写方法的地方
methods: {
handleBtnClick() {
// 反转字符串
this.content = this.content.split("").reverse().join("")
}
},
// 绑定点击事件需要使用 vue 内置的 v-on:事件名
template: `
<div>
{{ content }}
<button v-on:click="handleBtnClick">反转</button>
</div>
`
}).mount("#root")
</script>
</html>
可以看到,使用 vue 以后,不去面向 DOM 编程,而是面向数据编程。
2.2 显示隐藏功能实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Vue 的 CDN -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
content: "hello world",
show: true,
}
},
methods: {
handleBtnClick() {
this.show = !this.show;
}
},
// v-if 该元素是否存在取决于里边的对象
template: `
<div>
<span v-if="show">{{ content }}</span>
<button v-on:click="handleBtnClick">显示/隐藏</button>
</div>
`
}).mount("#root")
</script>
</html>
3. 编写 TodoList 小功能,了解循环和双向绑定
如果数据是数组的话,如果一个一个写然后渲染到页面上非常麻烦,因此就有 v-for 的方法来遍历。
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
list: ['hello', 'world', 'sjh']
}
},
template: `
<div>
<ul>
<li v-for="(item, index) of list">{{ item }} - {{ index }}</li>
</ul>
</div>
`,
}).mount("#root");
</script>
index 为数组的下标。
显示效果如下:
后面需要做的是,需要添加按钮来往 list 里边 push 输入的内容。所以需要绑定点击事件,然后用 v-model (双向绑定) 获取输入框里的内容,当点击添加的时候,把 data 里输入框的内容 push 到 list 里边。list 一旦更新,就会重新渲染模板。
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
inputValue: "",
list: ['hello', 'world', 'sjh']
}
},
methods: {
handleAddItem() {
this.list.push(this.inputValue);
this.inputValue = "";
}
},
template: `
<div>
<input type="text" v-model="inputValue" />
<button v-on:click="handleAddItem">增加</button>
<ul>
<li v-for="(item, index) of list">{{ item }} - {{ index }}</li>
</ul>
</div>
`,
}).mount("#root");
</script>
4. 组件概念初探,对 TodoList 进行组件代码拆分
一个大型网站,不可能所有的代码写在一个文件里,所以组件拆分就显得十分重要。
注册组件方法:
app.component("todo-item", {
template: `<div>hello world</div>`,
});
app.mount("#root");
这代表注册了一个组件,名称叫 todo-item
同样的,在组件内也可以使用 data,methods,生命周期函数等特性。
那么父组件怎么传递数据到子组件呢?先使用 v-bind 传值进去,然后子组件使用 props 接收即可。
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
inputValue: "",
list: ['hello', 'world', 'sjh']
}
},
methods: {
handleAddItem() {
this.list.push(this.inputValue);
this.inputValue = "";
}
},
template: `
<div>
<input type="text" v-model="inputValue" />
<button v-on:click="handleAddItem">增加</button>
<ul>
<todo-item
v-for="(item, index) of list"
v-bind:content="item"
v-bind:index="index"
/>
</ul>
</div>
`,
});
app.component("todo-item", {
props: ["content", "index"],
template: `<div>{{ index }} - {{ content }}</div>`,
});
app.mount("#root");
</script>