- 环境变量与模式
- 设置
- 基础
- 过滤器 观察属性 计算属性
- 表单绑定 表单修饰符
- 组件
- 路由 vue-router
- 事件多处理
- 其他
环境变量与模式
- 环境变量
.env
,使用变量 VUE_APP_
前缀
-
.env.development
开发环境
-
.env.production
生产环境
-
.env.local
git 忽略
- 模式
NODE_ENV
-
NODE_ENV=development
开发模式,用于 serve
-
NODE_ENV=production
生产模式,用于 build
和 test:e2e
-
NODE_ENV=test
测试模式,用于 test:unit
设置
{
"dev-build": "vue-cli-service build --mode development", // 指定模式
"browserslist": ["> 1%", "last 2 versions", "not ie <= 8"] // 浏览器兼容性
}
module.exports = {
outputDir: process.env.NODE_ENV === "production" ? "" : "dist",
baseUrl: process.env.NODE_ENV === "production" ? "/" : "/",
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
configureWebpack: (config) => {},
devServer: {
host: "0.0.0.0",
port: 8080,
https: false,
hotOnly: false,
proxy: null,
before: (app) => {},
}, // webpack-dev-server
parallel: require("os").cpus().length > 1, // 多核
pwa: {},
pluginOptions: {},
};
基础
-
v-if
显示条件
-
v-for
循环数组
-
v-bind
绑定数据
-
v-on
事件处理
-
v-model
双向绑定
过滤器 观察属性 计算属性
<div id="myApp">
<p>{{ item | toupper }}价格:{{ price }}円,含税价格:{{ priceInTax }}円</p>
<button @click="btnClick1(10800)">价格改为10800円</button>
<button @click="btnClick2(10800)">含税价格改为10800円</button>
</div>
<script>
var myApp = new Vue({
el: "#myApp",
data: { item: "Switch", price: 29980 }, // 观察属性需在初始声明,计算属性不需在初始声明
watch: {
// 观察 price,btnClick1() 改变 price
price: function (newVal, oldVal) {
console.log(newVal, oldVal);
this.priceInTax = Math.round(this.price * 1.08);
},
},
computed: {
// 计算 priceInTax
priceInTax: {
// 计算属性 .get(),相当于 priceInTax: function () { return this.price*1.08; },
get: function () {
return this.price * 1.08;
},
// 计算属性 .set(),btnClick2() 改变 priceInTax
set: function (value) {
this.price = value / 1.08;
},
},
},
filters: {
toupper: function (value) {
return value.toUpperCase();
},
},
methods: {
btnClick1: function (newPrice) {
this.price = newPrice;
},
btnClick2: function (newPrice) {
this.priceInTax = newPrice;
},
},
});
</script>
表单绑定 表单修饰符
<div id="myApp">
<!-- 表单复选 input[type="checkbox"] -->
<input
type="checkbox"
id="生化危机7"
value="生化危机7"
v-model="checkedGames"
/>
<label for="生化危机7">生化危机7</label>
<input
type="checkbox"
id="模拟飞行"
value="模拟飞行"
v-model="checkedGames"
/>
<label for="模拟飞行">模拟飞行</label><br />
<p>您选择的游戏是: {{ checkedGames }}</p>
<!-- 表单单选 input[type="radio"] -->
<input type="radio" id="male" value="男" v-model="pickedSex" />
<label for="male">男</label><br />
<input type="radio" id="female" value="女" v-model="pickedSex" />
<label for="female">女</label><br />
<p>性别: {{ pickedSex }}</p>
<!-- 表单下拉框单选/复选 select multiple为多选 -->
<select v-model="likedNBAStar" multiple style="width:200px;height:200px;">
<option>科比</option>
<option>詹姆斯</option>
</select>
<p>我喜欢: {{ likedNBAStar }}</p>
<!--表单修饰符 input[type="text"] textarea .lazy .number .trim -->
<label for="username">用户:</label>
<input
type="text"
id="username"
v-model.lazy="username"
@change="checkUsername($event)"
/>
<span v-if="checkUsernameOK">可注册</span>
<label for="age">年龄:</label>
<input type="number" id="age" v-model.number="age" />
<label for="content">个人简介:</label><br />
<textarea id="content" v-model.trim="content" cols="55" rows="8"></textarea>
<p>用户名:{{ username }}</p>
<p>年龄:{{ age }}</p>
<p>个人简介:{{ description }}</p>
</div>
<script>
var myApp = new Vue({
el: "#myApp",
data: {
checkedGames: [],
pickedSex: "",
likedNBAStar: null,
username: "",
checkUsernameOK: false,
age: "",
description: "",
},
methods: {
checkUsername: function (event) {
if (this.username.length > 0) this.checkUsernameOK = true;
else this.checkUsernameOK = false;
this.debugLog(event); // 事件信息
console.log(
event.srcElement.tagName,
event.srcElement.id,
event.srcElement.innerHTML,
event.key ? event.key : ""
);
},
},
});
</script>
组件
<div id="myApp">
<table border="1">
<tr>
<td>编号</td>
<td>游戏名称</td>
</tr>
<!-- 表行组件 is -->
<tr is="my-row1"></tr>
<tr is="my-row2"></tr>
</table>
<div>请输入名字:<input v-model="myname" /></div>
<custom
:score="50"
:pname="myname"
:age="25"
:detail="{ address:'earth', language:'世界语' }"
:a="6"
:b="12"
v-on:add_event="getAddResult"
></custom>
<p>{{ result }}</p>
<nba-all-stars c="奥尼尔"
>全明星阵容是:<span slot="pf">加内特</span></nba-all-stars
>
</div>
<script>
// 表行组件
Vue.component("my-row1", {
template: "<tr><td>(1)</td><td>塞尔达传说:荒野之息(3/3)</td></tr>",
});
Vue.component("my-row2", {
template: "<tr><td>(2)</td><td>新马里奥赛车(4/28)</td></tr>",
});
Vue.component("custom", {
template:
"<div>今天的天气是{{ todayWeather }}</div>" +
"<div>你好,{{ pname }},考试成绩{{ score }}分,{{ testResult }}</div>" +
"<div>年龄:{{ this.age }}岁<br/>地址:{{ this.detail.address }}<br/>语言:{{ this.detail.language }}</div>" +
'<div><button v-on:click="add">加</button></div>',
// 组件数据
data: function () {
return { todayWeather: "雨加雪" };
},
// 组件参数
props: ["score", "pname", "a", "b"],
// 组件参数验证
props: {
age: {
type: Number,
required: true,
validator: function (value) {
return value >= 0 && value <= 130;
},
},
detail: {
type: Object,
default: function () {
return { address: "US", language: "English" };
},
},
},
computed: {
testResult: function () {
var strResult = "";
if (this.score < 60) strResult = "不及格";
else if (this.score <= 100) strResult = "优秀";
return strResult;
},
},
methods: {
add: function () {
var value = 0;
value = this.a + this.b;
this.$emit("add_event", { result: value }); // 组件事件传递,在子组件中 $emit 触发事件
},
},
});
Vue.component("nba-all-stars", {
props: ["c"],
template:
'<div><slot></slot><br/>中锋:{{ c }}<br/>大前:<slot name="pf"></slot></div>', // 组件插槽
});
var WeatherComponent = { template: "<div>今天下雨</div>" }; // 组件局部注册,其他为全局注册
var myApp = new Vue({
el: "#myApp",
data: { myname: "Koma", result: 0 },
components: { "my-weather": WeatherComponent },
methods: {
// 组件事件传递,在父组件中 v-on 侦听事件
getAddResult: function (pval) {
this.result = pval.result;
},
},
});
</script>
路由 vue-router
// src/router/index.js 文件
import Vue from "vue";
import Router from "vue-router"; // 导入 router
import HelloWorld from "@/components/HelloWorld";
Vue.use(Router); // 注册 router
// 导出 router 对象
export default new Router({
routes: [
{
path: "/player/:uid/:nationality", // 动态路由
props: true, // 多参数路由需开 props
name: "Player",
component: Player,
components: { myPart1: Part1, myPart2: Part2 }, // 多路由,在 router-view 标签中调用 name="myPart1"
// 嵌套路由
children: [
{ path: "profile", component: PlayerProfile },
{ path: "stats", component: PlayerStats },
],
alias: "/aboutme", // 别名,地址栏显示
redirect: "/player/1", // 重定向,地址栏隐藏原地址
},
],
});
// src/main.js 文件
import router from "./router"; // 导入 router 对象
new Vue({
el: "#app",
router, // 注册 router 对象
components: { App },
template: "<App/>",
});
<template>
<div id="app">
<button @click="btnClick(1)">User1</button>
<router-link :to="{ name: 'Player', params: { uid: 2 }}">User2</router-link>
<router-link :to="{ path: '/player/3/stats' }">User3</router-link>
<router-link to="/player/4/usa">User4</router-link>
<router-view />
<!-- 路由出口,多路由调用 name="myPart1" -->
</div>
</template>
<script>
export default {
methods: {
btnClick(uid) {
this.$router.push({ path: "/player/${uid}/stats" });
this.$router.push({ name: "Player", params: { uid: uid } });
this.$router.push({ path: "/player", query: { uid: uid } }); // url-get 写法
this.$router.go(-1); // url 历史控制
},
},
};
// Player.vue 文件
export default {
name: "Player",
props: ["uid", "nationality"], // 调用 {{uid}} 和 {{nationality}} 接收数据,或调用 {{$route.params.uid}} 和 {{$route.params.nationality}} 接收数据
mounted() {}, // 子路由初次渲染
// 子路由再次渲染
beforeRouteUpdate(to, from, next) {
next();
},
};
</script>
事件多处理
<div id="hello-vue">
<h2>点击次数:{{ count }}</h2>
<button @click="btnClick1(), btnClick2($event)">点它加1</button>
</div>
<script>
const app = Vue.createApp({
data() {
return { count: 0 };
},
methods: {
btnClick1() {
this.count++;
},
btnClick2(event) {
console.log(event);
console.log(event.target);
console.log(event.target.attributes.class);
console.log(event.target.innerText);
},
},
});
app.mount("#hello-vue");
</script>
- 事件修饰符
-
.prevent
: event.preventDefault()
-
.stop
: event.stopPropagation()
.capture
.self
.once
.passive
- 按键修饰符
.enter
.tab
-
.delete
: 同时捕获删除和退格
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
-
.meta
: mac command
其他
分割杠
<template v-for="(tag, index) in job.tags">
<i v-if="index > 0"></i>{{ tag }}
</template>
路径
<template v-for="(item, index) in path">
<a :href="item.url">{{ item.title }}</a>
<i v-if="index < path.length - 1"></i>
</template>
图像初始未载入
<div v-if="user">
<img :src="user.avatar" />
</div>
网友评论