共计 7270 个字符,预计需要花费 19 分钟才能阅读完成。
环境搭建
引入 Vue
下载 js 文件:
用 <script>
标签引入,Vue 会被注册为一个全局变量。
用谷歌浏览器打开 html 文件,切换到控制台,会出现 2 个小提示。
Vue 开发者工具
第一个小提示,安装 Vue 开发者工具后,就不会出现提示了。
如果安装后还是不行的话,右键「Vue Devtools」->「管理扩展程序」,打开「允许访问文件网址」即可。
修改全局配置
第二个小提示,需要修改全局配置:
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false;
脚手架自定义创建项目
安装脚手架
全局安装:npm i -g @vue/cli
,如果之前安装过低版本的脚手架,想更新至最新版本的话,可先卸载当前版本再安装最新版本:npm un -g vue-cli
。
查看版本:vue -V
。
自定义创建项目
创建项目:vue create test
:
? Please pick a preset: Manually select features(选择自定义)
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors, Linter(选择需要的特性)
? Choose a version of Vue.js that you want to start the project with 2.x(这里选择 Vue2)
? Use history mode for router? (Requires proper server setup for index fallback in production) No(这里不使用历史模式,即 URL 路径中带有 #号)
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less(选择 CSS 预处理器)
? Pick a linter / formatter config: Standard(ESLint 代码检查和格式化工具,选择标准化无分号规范)
? Pick additional lint features: Lint on save(选择保存时检验)
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files(将 ESLint 配置文件放在单独文件中)
? Save this as a preset for future projects? No(是否保存当前配置作为将来项目的预设,这里选择 No)
? Pick the package manager to use when installing dependencies: Yarn(选择安装依赖时使用的包管理器,这里选择 Yarn)
启动项目
cd test
yarn serve
ESLint 代码规范
- JavaScript Standard Style 规范说明:https://standardjs.com/rules-zhcn.html
- ESLint 规则表:https://zh-hans.eslint.org/docs/latest/rules
使用 Prettier 代码格式化工具,格式化 Vue 代码时可能出现单引号变双引号等其他问题,这时需要自定义一些配置,可在项目根目录下添加配置文件.prettierrc:
{
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}
调整初始化目录
删除多余的文件
- src\assets\logo.png
- src\components\HelloWorld.vue
- src\views\AboutView.vue 和 src\views\HomeView.vue
修改路由配置和 App.vue
src\router\index.js:删除 HomeView 导入,删除 routes,默认路由规则设置为空数组,即:
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const router = new VueRouter({routes: []
});
export default router;
src\App.vue 修改为:
<template>
<div id="app">
<router-view />
</div>
</template>
<style lang="less"></style>
新增 api 和 utils 目录
在 src 目录下新增两个目录 api 和 utils:
- api 接口模块:发送 ajax 请求的接口模块
- utils 工具模块:自己装的一些工具方法模块
数据代理
Object.defineProperty()方法
这个方法接收三个参数:属性所在的对象、属性的名字、一个描述符对象。
<script>
let number = 20
let person = {
name: " 张三 ",
sex: " 女 ",
}
Object.defineProperty(person, "age", {
value: 18,
enumerable: true, // 控制属性是否可枚举,默认不可枚举
writable: true, // 控制属性是否可修改,默认不可修改
configurable: true, // 控制属性是否可删除,默认不可删除
})
</script>
该方法的第三个参数除了可以是数据属性,也可以是访问器属性:
<script>
let number = 20
let person = {
name: " 张三 ",
sex: " 女 ",
}
Object.defineProperty(person, "age", {// 当读取 person 的 age 属性时,get 函数 (getter) 会被调用,且返回值是 age 的值
get() {return number},
// 当修改 person 的 age 属性时,set 函数 (setter) 会被调用,且会收到修改的具体值
set(value) {number = value},
})
</script>
事件处理
基本使用
<body>
<div id="root">
<button @click="showInfo($event,666)"> 点 {{name}} 提示信息 </button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {name: " 李小龙 ",},
methods: {showInfo(event, number) {console.log(event, number);
},
},
});
</script>
</body>
事件修饰符
- prevent:阻止默认事件
- stop:阻止事件冒泡
- once:事件只触发一次
- capture:使用事件的捕获模式
- self:只有 event.target 是当前操作的元素时才触发事件
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕
修饰符可以连续写:
<body>
<div id="root" @click="showInfo">
<a href="https://www.baidu.com/" @click.stop.prevent="showInfo"> 点我提示信息 </a>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
methods: {showInfo() {alert(" 你好呀 ");
},
},
});
</script>
</body>
键盘事件
- 回车 => enter
- 删除 => delete(“删除”和“退格”键)
- 退出 => esc
- 空格 => space
- 换行 => tab(配合 keydown 使用)
- 上 => up
- 下 => down
- 左 => left
- 右 => right
系统修饰键:ctrl、alt、shift、meta,配合 keydown 使用。想用 keyup,还可以这样用:
// ctrl + y
@keyup.ctrl.y="showInfo"
计算属性
<div id="root">
姓:<input type="text" v-model="firstName" /><br /><br />
名:<input type="text" v-model="lastName" /><br /><br />
全名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
firstName: " 张 ",
lastName: " 三 ",
},
computed: {fullName() {return this.firstName + "-" + this.lastName;},
},
});
</script>
计算属性完整写法
<!DOCTYPE html>
<html lang="zh-CN">
<head> </head>
<body>
<!-- 第一步:准备容器 -->
<div id="app">
姓:<input type="text" v-model="firstName" /> + 名:<input type="text" v-model="lastName" /> = <span>{{fullName}}</span><br /><br />
<button @click="changeName"> 改名 </button>
</div>
<!-- 第二步:引包 -->
<script src="vue.js"></script>
<script>
// 第三步:创建实例,添加配置项
const app = new Vue({
el: '#app',
data: {
firstName: '张',
lastName: '三',
},
methods: {changeName() {this.fullName = '张小三'},
},
computed: {
fullName: {get() {return this.firstName + this.lastName},
set(value) {this.firstName = value.slice(0, 1)
this.lastName = value.slice(1)
},
},
},
})
</script>
</body>
</html>
监视属性
<body>
<div id="app">
<h2> 今天天气很{{info}}</h2>
<button @click="changeWeather"> 切换天气 </button>
</div>
<script>
const app = new Vue({
el: "#app",
data: {isHot: true,},
computed: {info() {return this.isHot ? " 炎热 " : " 凉爽 "},
},
methods: {changeWeather() {this.isHot = !this.isHot},
},
watch: {
isHot: {
immediate: true, // 初始化时让 handler 调用一下
// 当 isHot 发生改变时调用 handler
handler(newValue, oldValue) {console.log("isHot 被修改了 ", newValue, oldValue)
},
},
},
})
</script>
</body>
还可以这么写:
app.$watch("isHot", {
immediate: true,
handler(newValue, oldValue) {console.log("isHot 被修改了 ", newValue, oldValue)
},
})
深度监视
<script>
const app = new Vue({
el: "#app",
data: {
numbers: {
a: 10,
b: 20,
},
},
watch: {
numbers: {
deep: true, // 深度监视
handler() {console.log("numbers 改变了 ")
},
},
},
})
</script>
监视简写
watch: {isHot(newValue, oldValue) {console.log("isHot 被修改了 ", newValue, oldValue)
},
}
还可以简写:
app.$watch("isHot", function (newValue, oldValue) {console.log("isHot 被修改了 ", newValue, oldValue)
})
实时翻译案例
<!DOCTYPE html>
<html lang="zh-CN">
<head> </head>
<body>
<!-- 第一步:准备容器 -->
<div id="app"><textarea v-model="obj.words"></textarea>{{result}}</div>
<!-- 第二步:引包 -->
<script src="vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
// 第三步:创建实例,添加配置项
const app = new Vue({
el: '#app',
data: {
obj: {words: '',},
result: '',
},
watch: {'obj.words'(newValue) {
// 防抖优化(延时 300ms)clearInterval(this.timer)
this.timer = setTimeout(async () => {
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/api/translate',
params: {words: newValue,},
})
this.result = res.data.data
}, 300)
},
},
})
</script>
</body>
</html>
列表过滤
用 watch 实现:
<div id="app">
<h2> 人员列表 </h2>
<input type="text" placeholder=" 请输入名字 " v-model="keyWord" />
<ul>
<li v-for="(p,index) of filPersons" :key="index">
{{p.name}}--{{p.age}}
</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
keyWord: "",
persons: [{ id: "001", name: " 李小龙 ", age: 18},
{id: "002", name: " 李大龙 ", age: 19},
{id: "003", name: " 李中龙 ", age: 20},
{id: "004", name: " 周杰伦 ", age: 21},
],
filPersons: [],},
watch: {
keyWord: {
immediate: true,
handler(val) {this.filPersons = this.persons.filter((p) => {return p.name.indexOf(val) !== -1
})
},
},
},
})
</script>
用 computed 实现:
<script>
const app = new Vue({
el: "#app",
data: {
keyWord: "",
persons: [{ id: "001", name: " 李小龙 ", age: 18},
{id: "002", name: " 李大龙 ", age: 19},
{id: "003", name: " 李中龙 ", age: 20},
{id: "004", name: " 周杰伦 ", age: 21},
],
},
computed: {filPersons() {return this.persons.filter((p) => {return p.name.indexOf(this.keyWord) !== -1
})
},
},
})
</script>
列表排序
<div id="app">
<h2> 人员列表 </h2>
<input type="text" placeholder=" 请输入名字 " v-model="keyWord" />
<button @click="sortType=1"> 年龄升序 </button>
<button @click="sortType=2"> 年龄降序 </button>
<button @click="sortType=0"> 原顺序 </button>
<ul>
<li v-for="(p,index) of filPersons" :key="index">
{{p.name}}--{{p.age}}
</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
keyWord: "",
sortType: 0, // 0 原顺序 1 升序 2 降序
persons: [{ id: "001", name: " 李小龙 ", age: 28},
{id: "002", name: " 李大龙 ", age: 19},
{id: "003", name: " 李中龙 ", age: 20},
{id: "004", name: " 周杰伦 ", age: 11},
],
},
computed: {filPersons() {const arr = this.persons.filter((p) => {return p.name.indexOf(this.keyWord) !== -1
})
// 判断是否需要排序
if (this.sortType) {arr.sort((p1, p2) => {return this.sortType == 1 ? p1.age - p2.age : p2.age - p1.age})
}
return arr
},
},
})
</script>