Vue脚手架
javascript
1. Vue脚手架是Vue官方提供的标准化开发工具(开发平台)。它简化了程序员基于webpack创建工程化的Vue项目过程。
2. 最新的版本是`5.x`。
3. 文档: https://cli.vuejs.org/zh/。
Vue CLI 致力于将 Vue 生态中的工具基础标准化。
它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。
与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject。
入门使用
安装
javascript
CLI:Command Line Interface 命令行接口
@vue/cli 是一个全局安装的 npm 包,提供了终端里的 vue 命令。
bash
// 安装命令
npm install -g @vue/cli
# OR
yarn global add @vue/cli
// 查看版本命令
vue --version
# OR
vue -V @vue/cli 5.0.8
创建项目
bash
## 创建一个新项目
vue create first
## 选择自动配置还是手动配置,我们选择自动配置
Manually select features
## 选择插件 全选(a) 单选(空格)
babel、typscript、路由、Vuex、css预编译
## 选择Vue版本
选择2.x
## 选择是否使用 history 风格的路由
输入y
## 选择 `css` 预编译
Less
## 选择各插件配置的保存方式:选择各个配置单独文件
In dedicated config files
## 是否将这个配置保存下来:
选择N
## 执行依赖的下载
启动项目
bash
## 进入项目目录
cd first
## 启动项目
yarn serve 或 npm run serve
## 浏览器查看
配置信息调整
bash
C:\Users\zhangpeiyue\.vuerc
{
"useTaobaoRegistry": true,
"packageManager": "yarn",
"presets": {
"230320": {
"useConfigFiles": true,
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-router": {
"historyMode": true
},
"@vue/cli-plugin-vuex": {}
},
"vueVersion": "2",
"cssPreprocessor": "less"
}
}
}
Vue开发配置文件
javascript
const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
// 是否将依赖包中的程序进行转换。(兼容低版本浏览器)
transpileDependencies: true,
// 配置开发服务
devServer:{
port:80,
host:"zhangpeiyue.com",
open:true,// 启动项目后会自动打开浏览器
}
})
开放API
javascript
https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=上海&ci=10&channelId=4
https://api.github.com/search/repositories?q=r&sort=stars
https://api.github.com/search/users?q=r&sort=stars
组件命名
组件名称为大驼峰,不要用系统中命令常见的名称
方式1修改.eslintrc.js文件,关闭组件命名语法检查
javascript
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
//在rules中添加自定义规则
//关闭组件命名规则
"vue/multi-word-component-names":"off",
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}
方式2:修改Vue项目主配置文件vue.config.js文件
javascript
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false //关闭语法检查
})
项目结构
bash
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ ├── bootstrap.css: 第三方的CSS样式
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── components: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── jsconfig.json: js配置文件
├── package.json: 应用包配置文件
├── vue.config.js: vue配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
入口文件
src->main.js
javascript
import Vue from 'vue'
import App from './App.vue'
// Vue调试信息提示
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app') // 这里的id为app 在public -> index.html中
javascript
render: function (createElement) {
return createElement(App);
}
// 简写
render (createElement) {
return createElement(App);
}
// 进一步简写
render: h => h(App);
Vue 在调用 render 方法时,会传入一个 createElement 函数作为参数,也就是这里的 h 的实参是 createElement 函数,这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,调用了 mount 方法,渲染成真实 DOM 节点,并挂载到(通常是div app)节点上。
createElement函数是用来生成HTML DOM元素的,也就是generate HTML structures,也就是Hyperscript,这样作者才把createElement简写成h。h是vue.js里面的createElement函数,这个函数的作用就是生成一个VNode节点,render函数得到这个VNode节点之后,返回给vue.js的mount函数,渲染成真实DOM节点,并挂载到根节点上。
组件的使用
组件命名
组件的命名: 首字母大写
单文件组件
bash
组件内分为三层
结构层-<template>
不允许省略
有且只能有一个根元素
逻辑层-<script>
正常js代码处理逻辑
样式层-<style>
lang="less"属性 :css预处理为less,
scoped 属性:设置css为局部的,不会影响其他组件(原理是自动设置data-v-hash自定义属性)
src->App.vue主组件
vue
<!--
结构层-不允许省略
有且只能是一个根元素
可以省略this,这里的this指向VueComponent的实例vc
因为vue在解析template时使用了with(this),改变了template中的顶层作用域
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/with
-->
<template>
<div>
<h3 @click="num++">APP:{{num}}</h3>
<hr/>
<Child :num="num"></Child>
</div>
</template>
<!--逻辑层-->
<script>
import Child from "@/components/Child";
export default {
name: "App",
data(){
return {
num:1
}
},
// 设置子组件
components:{
Child
}
}
</script>
<!--样式层-->
<style lang="less" scoped>
div{
h3{
color:red;
}
}
</style>
src->Child.vue子组件
vue
<template>
<div>
<h3>Child:{{num}}</h3>
</div>
</template>
<script>
export default {
name: "Child",
// props:["num"],
props:{
num:{
type:Number,
default:100
}
},
beforeCreate() {
console.log("1-beforeCreate");
},
created(){
console.log("2-created");
},
beforeMount() {
console.log("3-beforeMount");
},
mounted(){
console.log("4-mounted");
},
beforeUpdate() {
console.log("1-beforeUpdate");
},
updated(){
console.log("2-updated");
}
}
</script>
<style scoped>
h3{
color:green;
}
</style>
src->main.js主入口文件
javascript
// 导入Vue构造函数对象
import Vue from "vue";
// 导入App对象,主组件
import App from "@/App";
// 创建Vue实例
new Vue({
// 渲染主组件视图
render:h=>h(App)
// 挂载到public->index.html的app标签上
}).$mount("#app");
public->index.html
javascript
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
组件省略this
javascript
可以省略this,这里的this指向VueComponent的实例vc;
因为vue在解析template时使用了with(this),改变了template中的顶层作用域;
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/with;
过滤器的使用
过滤器在Vue-cli脚手架上的使用
全局过滤器
方式1:放在入口文件中(src->main.js)使用,并且放在new Vue(){...}代码前使用。
javascript
// src->main.js
Vue.filter("date",function(t){
const timer = new Date(t);
return timer.getFullYear() + "-" +
(timer.getMonth() + 1).toString().padStart(2, 0) + "-" +
timer.getDate().toString().padStart(2, 0) + " " +
timer.getHours().toString().padStart(2, 0) + ":" +
timer.getMinutes().toString().padStart(2, 0) + ":" +
timer.getSeconds().toString().padStart(2, 0);
});
Vue.filter("currency",function(v,n=2,type="$"){
return type+v.toFixed(n);
})
方式2:抽离到文件夹中模块化使用(src->filters->index.js)
javascript
// src->main.js
import filters from "@/filters";
for(let key in filters){
Vue.filter(key,filters[key]);
}
javascript
// src->filters->index.js
export default {
date(t){
const timer = new Date(t);
return timer.getFullYear() + "-" +
(timer.getMonth() + 1).toString().padStart(2, 0) + "-" +
timer.getDate().toString().padStart(2, 0) + " " +
timer.getHours().toString().padStart(2, 0) + ":" +
timer.getMinutes().toString().padStart(2, 0) + ":" +
timer.getSeconds().toString().padStart(2, 0);
},
currency(v,n=2,type="$"){
return type+v.toFixed(n);
}
}
局部过滤器
在哪个组中注册的,只允许在哪个组件中使用
javascript
// src->App.vue
filters:{
date(t){
const timer = new Date(t);
return timer.getFullYear() + "-" +
(timer.getMonth() + 1).toString().padStart(2, 0) + "-" +
timer.getDate().toString().padStart(2, 0) + " " +
timer.getHours().toString().padStart(2, 0) + ":" +
timer.getMinutes().toString().padStart(2, 0) + ":" +
timer.getSeconds().toString().padStart(2, 0);
},
currency(v,n=2,type="$"){
return type+v.toFixed(n);
}
}
作为插件安装到Vue(全局)
方式1:定义一个过滤器对象并暴漏一个函数,然后在入口文件把过滤器插件安装到全局Vue构造函数中
src->filters->index.js
javascript
// src->filters->index.js
// 定义一个对象
const filters = {
date(t){
const timer = new Date(t);
return timer.getFullYear() + "-" +
(timer.getMonth() + 1).toString().padStart(2, 0) + "-" +
timer.getDate().toString().padStart(2, 0) + " " +
timer.getHours().toString().padStart(2, 0) + ":" +
timer.getMinutes().toString().padStart(2, 0) + ":" +
timer.getSeconds().toString().padStart(2, 0);
},
currency(v,n=2,type="$"){
return type+v.toFixed(n);
}
};
// 暴漏一个函数 fun(Vue){...}
export default function(V){
for(let key in filters){
V.filter(key,filters[key]);
}
}
src->main.js
javascript
// src->main.js
// 导入Vue构造函数对象
import Vue from "vue";
// 导入APP主组件
import App from "@/App";
// 导入过滤器对象
import filters from "@/filters";
// 安装过滤器插件
// filters的两种类型:
// 1- 如果filters暴漏是一个对象,Vue.use会调用对象下的install方法,并传递Vue
// 2- 如果filters暴漏是一个函数,会直接调用该函数,并传递Vue
Vue.use(filters);
方式2:定义一个过滤器对象并暴漏一个对象,然后在入口文件把过滤器插件安装到全局Vue构造函数中
javascript
// src->filters->index.js
// 定义一个对象
const filters = {
date(t){
const timer = new Date(t);
return timer.getFullYear() + "-" +
(timer.getMonth() + 1).toString().padStart(2, 0) + "-" +
timer.getDate().toString().padStart(2, 0) + " " +
timer.getHours().toString().padStart(2, 0) + ":" +
timer.getMinutes().toString().padStart(2, 0) + ":" +
timer.getSeconds().toString().padStart(2, 0);
},
currency(v,n=2,type="$"){
return type+v.toFixed(n);
},
install(V) {
for (let key in filters) {
V.filter(key, filters[key]);
}
},
};
// 暴漏一个对象
export default filters;
入口文件通过插件形式安装过滤器到全局
javascript
// src->main.js
// 导入Vue构造函数对象
import Vue from "vue";
// 导入APP主组件
import App from "@/App";
// 导入过滤器对象
import filters from "@/filters";
// 安装过滤器插件
// filters的两种类型:
// 1- 如果filters暴漏是一个对象,Vue.use会调用对象下的install方法,并传递参数Vue(构造函数)
// 2- 如果filters暴漏是一个函数,会直接调用该函数,并传递参数Vue(构造函数)
Vue.use(filters);
axios的使用
安装axios插件
bash
cnpm install axios
通过axios获取数据
vue
// src->App.vue
<template>
<div>
<h3>App</h3>
</div>
</template>
<script>
// 导入axios对象
import axios from "axios";
// 暴漏
export default {
name: "App",
data(){
return {
items:[]
}
},
async mounted(){
// 方式3 async await 函数
const {data} = await axios.get("https://api.github.com/search/repositories",{
params: {
q: "r",
sort: "stars"
}
});
this.items = data.items;
}
}
</script>
<style scoped>
</style>
axios加载中
src->App.vue
vue
<template>
<div>
<h3>App</h3>
<h3 v-if="isLoading">正在拼命加载中……</h3>
<h3 v-else-if="isError">产生异常,请稍后再试……</h3>
<template v-else>
<div v-for="item in items" :key="item.id">
<p>{{item.full_name}}</p>
</div>
</template>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
data(){
return {
items:[],
isLoading:true,
isError:false,// 是否有异常
}
},
async mounted(){
try{
const {data} = await axios.get("https://api.github.com/search/repositories",{
params: {
q: "r",
sort: "stars"
}
});
this.items = data.items;
this.isLoading = false;
}catch (err){
this.isLoading = false;
this.isError= true;
}
}
}
</script>
<style scoped>
</style>
axios封装
方式一:将axios信息抽离到src->request->index.js,然后使用把axios用插件安装到Vue中
src->request->index.js
javascript
// src->request->index.js
// 导入axios对象
import axios from "axios";
// 设置baseURL
axios.defaults.baseURL = "https://api.github.com";
// 设置拦截器
axios.interceptors.response.use(res=>{
// 放行
return res.data;
});
// 暴漏数据,暴漏一个函数
export default function(Vue){
// 把axios对象设置为Vue实例的$axios属性
Vue.prototype.$axios = axios;
}
src-main.js
javascript
// src-main.js
import Vue from "vue";
import App from "@/App";
import axios from "@/request/index";
new Vue({
render:h=>h(App),
beforeCreate() {
// 安装axios插件
Vue.use(axios);
}
}).$mount("#app");
src->App.vue
vue
<template>
<div>
<h3>App</h3>
<h3 v-if="isLoading">正在拼命加载中……</h3>
<h3 v-else-if="isError">产生异常,请稍后再试……</h3>
<template v-else>
<div v-for="item in items" :key="item.id">
<p>{{item.full_name}}</p>
</div>
</template>
</div>
</template>
<script>
export default {
name: "App",
data(){
return {
items:[],
isLoading:true,
isError:false,// 是否有异常
}
},
async mounted(){
try{
const {items} = await this.$axios.get("/search/repositories",{
params: {
q: "r",
sort: "stars"
}
});
this.items = items;
this.isLoading = false;
}catch (err){
this.isLoading = false;
this.isError= true;
}
}
}
</script>
<style scoped>
</style>
方式二:将axios信息抽离到src->request->index.js,直接将暴漏的对象设置为Vue实例的属性$axios
javascript
// src->request->index.js
import axios from "axios";
axios.defaults.baseURL = "https://api.github.com";
axios.interceptors.response.use(res=>{
return res.data;
});
暴漏数据,暴漏一个对象
export default axios;
javascript
// src-main.js
import Vue from "vue";
import App from "@/App";
import axios from "@/request/index";
new Vue({
render:h=>h(App),
beforeCreate() {
// 将暴漏的对象设置为Vue实例的属性$axios
Vue.prototype.$axios = axios;
}
}).$mount("#app");
方式三:直接在src->main.js中设置axios对象
javascript
// src-main.js
import Vue from "vue";
import App from "@/App";
import axios from "@/request/index";
new Vue({
render:h=>h(App),
beforeCreate() {
axios.defaults.baseURL = "https://api.github.com";
axios.interceptors.response.use(res=>{
return res.data;
})
Vue.prototype.$axios = axios;
}
}).$mount("#app");