VUE配置
切换国内下载源
npm config set registry http://registry.npm.taobao.org
安装vue
npm install vue -g
安装VUE-CLI
快速构建vue项目的工具
2.X版本
npm install vue-cli -g
3.X版本
如果以及安装过2.X或3.X版本,需要先卸载
卸载2.X:npm uninstall vue-cli -g
卸载3.X:npm uninstall @vue/cli -g
安装3.X版本
npm install @vue/cli –g
安装webpack
npm install webpack -g
安装vue-router
npm install vue-router -g
常用命令
源相关
1.查看镜像源
npm get registry
2.切换官方源
npm config set registry http://www.npmjs.org
3.切换淘宝源
npm config set registry http://registry.npm.taobao.org
其他
# 查看npm版本
npm -v
# 查看当前项目的依赖
npm ls
# 查看 npm 的配置
npm config list -l
# 安装模块
npm install (简写:npm i) 模块名 (当前应用安装至package.json的dependencies中)
npm install 模块名 -g (全局安装)
npm i 模块名 --save-prod(简写:-P) (生产环境安装)
npm i 模块名 --save-dev(简写:-D) (开发环境安装至package.json的devDependencies)
# 更新模块
npm update 模块名
...(同安装模块)
# 卸载模块
npm uninstall 模块名
...(同安装模块)
快速构建vue项目
输入命令构建名为vue-demo
的项目
vue create vue-demo
剩下的根据需求自己选择即可
各文件作用
node_modules
里面放置所有的npm下载的依赖
public
存放项目的静态资源(
webpack
打包时会直接放入dist
文件夹内)
src
开发的应用的包
assets
存放src内组件要使用的静态资源(
webpack
打包时会被当成一个模块打包到js
文件夹里)
components
放置非路由组件(全局组件),公共组件
App.vue
根(主)组件
main.js
主项目的入口文件,最先执行,主要作用是初始化vue实例,并引入所需要的插件
.gitignore
配置git提交时忽略上传的文件
babel.config.js
项目的配置文件,一般用于兼容es5和es6语法
package-lock.json
可以删除,是一个缓存文件
package.json
记录vue项目的相关信息
veu3完整的组件
<template>
<div class="hello">
<h1>{{ message }}</h1>
<text v-text="counts"></text>
<br>
<input type="button" @click="add" value="按钮">
</div>
</template>
<script>
// import ...导入子组件
export default { // 导出组件
name: 'HelloWorld', // 组件名
data() { // 存放数据
return {
message: "你好哇!",
counts: 1
}
},
methods: { // 存放方法函数
add() {
this.counts += 1
}
},
components: { // 导入的组件名
// 组件名
}
}
</script>
// scoped表示当前样式只在当前组件中生效
<style scoped>
</style>
指令
v-text
与
{{message}}
相比会替换标签中的所有文本内容
v-html
文本中的html标签会被解析出来
v-on
事件绑定,形如
v-on:click
与@click
,两者是等价的
v-bing
属性绑定,
v-bind:title="message"
可以简写为:title="message"
v-show
设置元素是否隐藏,
v-show="true"
显示,v-show="false"
隐藏,里面是一个bool值,可以自己设置
v-if、v-else、v-else-if
条件判断
v-if
与v-show
的区别是:前者会直接销毁不符合条件的内容(组件)或重建布拉布拉,而后者只是隐藏起来不显示,内容会一直渲染。对于频繁需要切换的场景,应使用后者
v-for
<div v-for="item in items" :key="item.id(index)">
<!-- 内容 -->
</div>
唯一的
key
记录每个数据的下标、用于跟踪判断列表或数组中的新旧数据,然后渲染新的数据,旧的数据不需要再次渲染,提高性能
v-model
数据双向绑定,修改表单的值,属性的值会同步修改,反之亦然
v-model.lazy
当用户输入的数据失去焦点时才会同步修改
v-model.trim
会自动过滤输入首尾的空格
组件
加载组件
- 引入组件:import ...
- 挂载组件:components: {...}
- 显示组件
props组件间参数传递
proprs 参数的传递应为单向的父传子
父组件App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png">
<propsTest :titles="titles" :age="age" :arr="arr"/>
</template>
<script>
import propsTest from "./components/propsTest.vue"
export default {
name: 'App',
components: {
propsTest
},
data() {
return {
titles: "这是一个标题",
age: 20,
arr: [1, 2, 3]
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
子组件propsTest.vue
<template>
<h1>{{ titles }}</h1>
<p>age = {{ age }}</p>
<ul>
<li v-for="item in arr" :key="index">{{ item }}</li>
</ul>
</template>
<script>
export default {
name: 'propsTest',
props: {
titles: {
type: String, //参数校验
// default: "", //默认值,如果未传递参数就用默认值替代
required: true //设置当前属性必须传值
},
age: {
type: Number,
default: 0
},
// 数组和对象的默认值应用工厂函数返回
arr: {
type: Array,
default() {
return { }
}
}
},
data() {
return {
}
}
}
</script>
emit组件参数传递
emit可以使得子组件参数传递给父组件
父组件App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png">
<p>{{ message }}</p>
<myComponentVue @onEvent="getDataHandle"/> // 函数接受传过来的数据
</template>
<script>
import myComponentVue from './components/myComponent.vue';
export default {
name: 'App',
components: {
myComponentVue
},
data() {
return {
message: ""
}
},
methods: {
getDataHandle(data) {
this.message = data; //获取data参数
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
子组件myComponent.vue
<template>
<button @click="sendClickHandle">点我试试</button>
</template>
<script>
export default {
name: 'myComponent',
data() {
return {
message: "我是components的参数!"
}
},
methods: {
sendClickHandle() {
// 第一个参数是一个字符串,应与父组件中的@..=""对应
// 第二个参数是要传递的数据
this.$emit("onEvent", this.message)
}
}
}
</script>
组件生命周期
创建时:beforeCreate
、created
渲染时:beforeMount
、mounted
更新时:beforeUpdate
、updated
卸载时:beforeUnmount
、unmounted
注:vue3
增加了setup
,其运行在beforeCreate
、created
之前
Axios
网络请求
首先导入axios
,将axios
放入main.js
中导入全局
main.js
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import axios from "axios"
const app = createApp(App)
app.config.globalProperties.$axios = axios // 将axios挂载到全局
app.mount('#app')
axiosTest.vue
<template>
<div class="hello">
<p>
{{ ans.title }}
</p>
</div>
</template>
<script>
import querystring from "querystring"
export default {
name: "axiosTest",
data() {
return {
ans: {}
}
},
mounted() {
// this.$axios({
// method: "post",
// url: "http://iwenwiki.com/api/blueberrypai/login.php",
// data: querystring.stringify({
// user_id: "[email protected]",
// password: "iwen123",
// verification_code: "crfvw"
// })
// }).then(res => {
// console.log(res.data)
// })
// 简洁写法
this.$axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
.then(res => {
this.ans = res.data.chengpinDetails[0],
console.log(res.data);
})
this.$axios.post("http://iwenwiki.com/api/blueberrypai/login.php", querystring.stringify({
user_id: "[email protected]",
password: "iwen123",
verification_code: "crfvw"
})).then(res => {
console.log(res.data);
})
}
}
</script>
请求封装
在src
文件下创建utils
文件,再在里面创建request.js
文件,里面编写请求响应的处理
import axios from "axios";
import querystring from "querystring";
const errorHandle = (status, info) => {
switch(status) {
case 400:
console.log("语义有误");
break;
case 401:
console.log("服务器认证失败");
break;
case 403:
console.log("服务器拒接访问");
break;
case 500:
console.log("地址错误");
break;
case 502:
console.log("服务器无响应");
break;
default:
console.log(info);
break;
}
}
const instance = axios.create({ // 定义一个请求对象
// 请求配置
timeout: 5000
})
instance.interceptors.request.use(
config => {
if (config.method === "post") { // 处理请求数据
config.data = querystring.stringify(config.data)
}
return config;
},
error => {
return Promise.reject(error);
}
)
instance.interceptors.response.use(
response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
error => {
errorHandle(error.status, error.info);
}
)
export default instance; // 抛出对象
在src
文件夹下创建名为api
的文件,再在里面创建两个js
文件
path.js
const base = {
baseUrl: "http://iwenwiki.com",
chengpinUrl: "/api/blueberrypai/getChengpinDetails.php"
}
export default base;
index.js
import axios from "../utils/request";
import path from "./path"
const api = {
getChengpin() {
return axios.get(path.baseUrl + path.chengpinUrl);
}
}
export default api;
再在组件axiosTest.vue
内调用api/index.js
<template>
<div class="hello">
<p>
{{ ans.title }}
</p>
</div>
</template>
<script>
import api from "../api/index"
export default {
name: "axiosTest",
data() {
return {
ans: {}
}
},
mounted() {
api.getChengpin().then(res => {
this.ans = res.data.chengpinDetails[0],
console.log(res.data);
})
}
}
</script>
跨域问题
什么是跨域
前端调用后端的接口时,出现协议、域名、端口错误的情况,叫做跨域
前端解决方案
配置代理
vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
'/api': {
target: 'http://iwenwiki.com', // 放置跨域的域名地址
changeOrifin: true
}
}
}
})
axiosTest.vue
<script>
import axios from "axios";
export default {
name: "axiosTest",
mounted() {
axios.get("/api/FingerUnion/list.php")
.then(res => {
console.log(res.data);
})
}
}
</script>
最后重启,才能拿到数据
Vue-router
用于控制页面跳转关系
安装路由
npm i vue-router
创建界面
在src
包下创建一个views
文件夹,在文件夹内再创建两个vue
组件
HomeVue.vue
<template>
<h1>主页</h1>
</template>
AboutVue.vue
<template>
<h1>关于页面</h1>
</template>
配置路由
在src
包下创建router
文件夹,在文件夹下创建index.js
文件
index.js
import { createRouter, createWebHashHistory } from "vue-router"
import HomeVue from "../views/HomeVue"
const routes = [
{ path: '/', component: HomeVue },
// 除了首页以外采用异步加载,不点击页面就不加载
{ path: '/about', component: () => import("../views/AboutVue") },
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router;
在main.js
加入两行,引入路由
import router from './router'
app.use(router)
App.vue
<template>
<RouterLink to="/">首页 | </RouterLink>
<RouterLink to="/about">关于</RouterLink>
<RouterView></RouterView>
</template>
<script>
export default {
name: 'App',
}
</script>
参数传递
views
包下新建NewsView.vue
、NewsDetails.vue
NewsView.vue
<template>
<ul>
<li>
<RouterLink to="/news/百度">百度新闻</RouterLink>
<RouterLink to="/news/网易">网易新闻</RouterLink>
<RouterLink to="/news/头条">头条新闻</RouterLink>
</li>
</ul>
</template>
NewsDetails.vue
<template>
<!-- $route.params.name获取参数 -->
<h2>{{ $route.params.name }}新闻详情</h2>
</template>
配置路由
index.js
import { createRouter, createWebHashHistory } from "vue-router"
import HomeVue from "../views/HomeVue"
const routes = [
{ path: '/', component: HomeVue },
// 除了首页以外采用异步加载,不点击页面就不加载
{ path: '/about', component: () => import("../views/AboutVue") },
{ path: '/news', component: () => import("../views/NewsView")},
{ path: '/news/:name', component: () => import("../views/NewsDetails")}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router;
App.vue
<template>
<nav>
<RouterLink to="/">首页|</RouterLink>
<RouterLink to="/about">关于|</RouterLink>
<RouterLink to="/news">新闻</RouterLink>
</nav>
<RouterView></RouterView>
</template>
<script>
export default {
name: 'App',
}
</script>
嵌套路由
在src/views
下新建文件夹aboutSub
,里面放AboutVue.vue
页面的二级嵌套页面:AboutUs.vue
、AboutInfo.vue
AboutUs.vue
<template>
<h2>关于我们</h2>
</template>
AboutInfo.vue
<template>
<h2>关于信息</h2>
</template>
AboutVue.vue
<template>
<RouterLink to="/about/us">关于我们</RouterLink> |
<RouterLink to="/about/info">关于信息</RouterLink>
<h1>关于页面</h1>
<RouterView></RouterView>
</template>
在index.js
内配置嵌套路由
import { createRouter, createWebHashHistory } from "vue-router"
import HomeVue from "../views/HomeVue"
const routes = [
{ path: '/', component: HomeVue },
// 除了首页以外采用异步加载,不点击页面就不加载
{ path: '/about', component: () => import("../views/AboutVue"),
redirect: "/about/us", // 重定向,每次点击到/about页面默认先加载/about/us
children: [
{
path: 'us',
component: () => import("../views/aboutSub/AboutUs")
},
{
path: 'info',
component: () => import("../views/aboutSub/AboutInfo")
}
]},
{ path: '/news', component: () => import("../views/NewsView")},
{ path: '/news/:name', component: () => import("../views/NewsDetails")}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router;
Vuex
用于管理组件间的状态
state
里面存放数据
安装vuex
npm i vuex
在src
下创建store
文件夹,再在里面创建index.js
import { createStore } from 'vuex'
export default createStore ({
state: {
count: 20
}
})
在src/main.js
内新增两行
import store from './store'
app.use(store)
两种读取vuex中数据的方法
App.vue
<template>
<!-- 第一种 -->
<p>count = {{ $store.state.count }}</p>
<p>count = {{ count }}</p>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'App',
// 第二种
computed: {
...mapState(['count'])
}
}
</script>
getters
用于读取state中的数据
index.js
export default createStore ({
state: {
count: 20
},
getters: {
getCount(state) {
return state.count > 0 ? state.count : "数据异常"
}
}
})
App.vue
<template>
<!-- 第一种 -->
<p>count = {{ $store.state.count }}</p>
<p>count = {{ getCount }}</p>
</template>
<script>
import { mapGetters, mapState } from 'vuex';
export default {
name: 'App',
// 第二种
computed: {
...mapGetters(['getCount'])
}
</script>
mutations
同步修改state的值
index.js
import { createStore } from 'vuex'
export default createStore ({
state: {
count: 20
},
getters: {
getCount(state) {
return state.count > 0 ? state.count : "数据异常"
}
},
mutations: {
addCount(state, num) {
state.count += num
}
}
})
App.vue
<template>
<!-- 第一种 -->
<p>count = {{ $store.state.count }}</p>
<p>count = {{ getCount }}</p>
<button @click="addClickHandle">增加</button>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'App',
// 第二种
computed: {
...mapGetters(['getCount'])
},
methods: {
...mapMutations(['addCount']),
addClickHandle() {
// 调用mutations内的方法
// this.$store.commit("addCount", 10)
this.addCount(10);
}
}
}
</script>
action
action可以同步操作和异步操作,mutations只能同步操作
index.js
import axios from 'axios'
import { createStore } from 'vuex'
export default createStore ({
state: {
count: 20
},
getters: {
getCount(state) {
return state.count > 0 ? state.count : "数据异常"
}
},
mutations: {
addCount(state, num) {
state.count += num
}
},
actions: {
asyncAddCount({ commit }) {
axios.get("http://iwenwiki.com/api/generator/list.php")
.then(res => {
commit("addCount", res.data[0])
})
}
}
})
App.vue
<template>
<!-- 第一种 -->
<p>count = {{ $store.state.count }}</p>
<p>count = {{ getCount }}</p>
<button @click="addClickHandle">增加</button>
<button @click="addAsyncClickHandle">异步增加</button>
</template>
<script>
import { mapActions, mapGetters, mapMutations } from 'vuex';
export default {
name: 'App',
// 第二种
computed: {
...mapGetters(['getCount'])
},
methods: {
...mapMutations(['addCount']),
...mapActions(['asyncAddCount']),
addClickHandle() {
// 调用mutations内的方法
// this.$store.commit("addCount", 10),
this.addCount(20);
},
addAsyncClickHandle() {
// this.$store.dispatch("asyncAddCount"),
this.asyncAddCount();
}
}
}
</script>
标签:npm,count,VUE,default,笔记,学习,vue,组件,import
From: https://www.cnblogs.com/RCLiu/p/16865995.html