使用vue创建项目
http://vue_book.siwei.me/
安装nodejs
Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/
C:\Users\Administrator>node -v
v14.16.1
npm使用镜像
# 临时使用
C:\Users\Administrator>npm --registry https://registry.npm.taobao.org install express
# 永久使用
C:\Users\Administrator>npm config set registry https://registry.npm.taobao.org
# 通过命令查看是否成功
C:\Users\Administrator>npm config get registry
C:\Users\Administrator>npm info express
# 恢复官方地址
C:\Users\Administrator>npm config set registry http://registry.npmjs.org
安装 cnpm
C:\Users\Administrator>npm -v
6.14.12
C:\Users\Administrator>npm install -g cnpm --registry=https://registry.npm.taobao.org
C:\Users\Administrator>cnpm -v
win32 x64 10.0.18363
registry=https://r.npm.taobao.org
安装 vue 和 vue-cli
要同时安装 vue和 vue-cli这两个node package.
-g 表示给他们安装成全局可以使用的包。
C:\Users\Administrator>cnpm install vue vue-cli -g
C:\Users\Administrator>vue -V
2.9.6
Element UI 和 vue的关系
Element UI官网:https://element.eleme.cn/2.0/#/zh-CN
Element UI 是一套采用 Vue 2.0 作为基础框架实现的组件库,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的组件库,提供了配套设计资源,帮助网站快速成型
调试工具 vConsole
<script src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.15.0/vconsole.min.js"></script>
<script>
new VConsole();
</script>
安装sass
node和sass的版本有对应关系
# 查看node版本
C:\Users\Administrator>node -v
v14.17.0
# node v14 对应 node-sass 和 sass-loader版本如下
C:\Users\Administrator>npm install node-sass@4.13.1 --save-dev
C:\Users\Administrator>npm install sass-loader@7.3.1 --save-dev
# 错误安装后可以卸载
C:\Users\Administrator>npm uninstall node-sass
基于 webpack 模板的新项目
# 基于 webpack 模板的新项目
D:\vue_example>vue init webpack my-project
# 进入初始化的项目目录
D:\vue_example>cd my-project
# 安装项目
D:\vue_example\my-project>cnpm install
# 运行项目 运行成功可访问: http://localhost:8080
D:\vue_example\my-project>cnpm run dev
项目文件结构
▸ build/ // 编译用到的脚本
▸ config/ // 各种配置
▸ dist/ // 打包后的文件夹
▸ node_modules/ // node第三方包
▸ src/ // 源代码
▸ static/ // 静态文件, 暂时无用
index.html // 最外层文件
package.json // node项目配置文件
build 保留各种打包脚本
保留各种打包脚本。不可或缺,不要随意修改。
展开后如下:
▾ build/
# 打包使用, 不要修改。
build.js
# 检查npm的版本, 不要修改。
check-versions.js
# 是在开发时使用的服务器脚本。不要修改。
# (借助于node这个后端语言,我们 在做vuejs开发时,可以通过 $npm run dev这个命令,打开一个小的server, 运行vuejs. )
dev-client.js
dev-server.js
# 不要修改。 做一些css/sass 等文件的生成。
utils.js
# 非常重要的配置文件,不要修改。内容是用来辅助加载vuejs用到的css source map等内容。
vue-loader.conf.js
# 这三个都是基本的配置文件。不要修改。
webpack.base.conf.js
webpack.dev.conf.js
webpack.prod.conf.js
config 跟部署和配置相关
▾ config/
# 开发模式下的配置文件,一般不用修改。
dev.env.js
# 生产模式下的配置文件,一般不用修改。
prod.env.js
# 很重要的文件,
# 定义了开发时的端口(默认是8080),
# 定义了图片文件夹(默认static),
# 定义了开发模式下的 代理服务器. 我们修改的还是比较多的。
index.js
eslint禁用 config\index.js
module.exports = {
dev: {
useEslint: false
}
}
dist 打包之后的文件所在目录
这个文件夹不要放到git中。
▾ dist/
▾ static/
▾ css/
app.d41d8cd98f00b204e9800998ecf8427e.css
app.d41d8cd98f00b204e9800998ecf8427e.css.map
▾ js/
app.c482246388114c3b9cf0.js
app.c482246388114c3b9cf0.js.map
manifest.577e472792d533aaaf04.js
manifest.577e472792d533aaaf04.js.map
vendor.5f34d51c868c93d3fb31.js
vendor.5f34d51c868c93d3fb31.js.map
index.html
node_modules node项目所用到的第三方包
node项目所用到的第三方包,特别多,特别大。 $ npm install 所产生。
这个文件夹不要放到git中。
src 最最核心的源代码所在的目录。
▾ src/
# 用到的图片
▾ assets/
logo.png
# 用到的"视图"和"组件"所在的文件夹。(最最核心)
▾ components/
Book.vue
BookList.vue
Hello.vue
# 路由文件。 定义了各个页面对应的url.
▾ router/
index.js
# 如果index.html 是一级页面模板的话,这个App.vue就是二级页面模板。
# 所有的其他vuejs页面,都作为该模板的 一部分被渲染出来。
App.vue
# 废代码。没有实际意义,但是为了支撑整个vuejs框架,存在很必要。
main.js
创建一个页面
创建页面需要两步:
- 新建路由
- 新建vue页面
新建一个路由
路由文件是 src/router/index.js, 打开之后, 我们增加两行:
import Vue from 'vue'
import Router from 'vue-router'
// 增加这一行, 作用是引入 First 这个component
import First from '@/components/First'
Vue.use(Router)
export default new Router({
routes: [
// component定义有两种方式:
{// 访问url: http://localhost:8080/#/First02
path: '/First',
name: 'First',
component: First
},
{// 增加下面几行, 表示定义了url http://localhost:8080/#/First02
path: '/First02',
name: 'First02',
component: (resolve) => require(['@/components/First'], resolve)
}
]
})
创建一个新的component
我们要创建 src/components/First.vue, 这个文件.
如下:
<template>
<div >
This is my first vue!
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
创造可以接收参数的component并调用
src\components\vuePlugin\FirstComponent.vue
<template>
<div style="border:1px solid yellowgreen; padding: 10px; margin: 1em;">
<h1>{{msg}} : {{title}}</h1>
<select v-if="dataList != null">
<option :key="item.id" v-for="(item) in dataList">{{item}}</option>
</select>
</div>
</template>
<script>
export default {
name: '',
props: ['title', 'dataList'],
data () {
return {
msg: 'This is my first component !'
}
}
}
</script>
src\components\Test02.vue
<template>
<div >
<FirstComponent title="阳江欢迎您" :dataList="dataList"/>
</div>
</template>
<script>
import FirstComponent from '@/components/vuePlugin/FirstComponent'
export default {
components: { FirstComponent },
data () {
return {
dataList: ['成都', '上海', '广州']
}
}
}
</script>
src\router\index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/Test02',
name: 'Test02',
component: (resolve) => require(['@/components/Test02'], resolve)
}
]
})
通过axios调用在static文件内的json
使用 cnpm 安装 axios
cnpm install axios --save
修改 main.js,添加下面两行
import axios from 'axios'
Vue.prototype.$http = axios
修改 src\router\index.js
新增src\components\TestJson.vue
<template>
<div>
<button @click="ajaxTestFn">Ajax请求</button>
</div>
</template>
<script>
export default{
name: 'Forms',
components: {},
data () {
return {}
},
methods: {
ajaxTestFn () {
this.$http.get('/static/test.json').then(res => {
// res是请求到的值
this.menu = res.data
console.log(res.data)
})
}
}
}
</script>
测试url:
static\test.json
http://localhost:8080/static/test.json
跨域配置代理 proxyTable
/config/index.js
module.exports = {
...
dev: {
proxyTable: {
'/api': {
target: `http://target:3000`,
ws: true,
changeOrigin: true,
pathRewrite: {
'^/api': 'http://target:3000/my-api'
},
logLevel: 'debug'
},
}
...
}
父子组件联动
父组件 test.vue
<template>
<div id="test">
{{ formData }}
<div></div>
<MyInput
:codeField="'userName'"
:code="formData['userName']"
@changeCode="getComponentData"
></MyInput>
<MySelect
:codeField="'genderCode'"
:textField="'genderName'"
:code="formData['genderCode']"
:text="formData['genderName']"
@changeCode="getComponentData"
></MySelect>
</div>
</template>
<script>
import MyInput from "@/views/test/myInput.vue";
import MySelect from "@/views/test/mySelect.vue";
export default {
name: "test",
components: { MyInput, MySelect },
data() {
return {
formData: {
genderCode: "1",
genderName: "",
userName:""
},
};
},
methods: {
getComponentData(val, txt, valField, txtField) {
this.formData[valField] = val;
},
},
};
</script>
子组件 myInput.vue
<template>
<div>
<input @blur="myChangeValue" v-model="modelCode" />
</div>
</template>
<script>
export default {
name: "myInput",
props: {
// 传入值
code: { type: String, default: "" },
codeField: { type: String, default: "" },
},
data() {
return {
modelCode:this.code,
};
},
methods: {
myChangeValue() {
this.$emit("changeCode", this.modelCode, null, this.codeField, null);
},
},
};
</script>
子组件 mySelect.vue
<template>
<section>
<el-select
:placeholder="placeholder"
:multiple="isMul"
collapse-tags
:filterable="filterable"
v-model="modelCode"
@clear="clearCodeSelect"
:clearable="clearable"
@change="sendCode1"
:disabled="disabled"
:readonly="readonly"
size="small"
>
<el-option
v-for="item in optionDatas"
:key="
item[optionFields.length > 1 ? optionFields[0] : defOptionFields[0]]
"
:label="
item[optionFields.length > 1 ? optionFields[1] : defOptionFields[1]]
"
:value="
item[optionFields.length > 1 ? optionFields[0] : defOptionFields[0]]
"
>{{
item[optionFields.length > 1 ? optionFields[1] : defOptionFields[1]]
}}</el-option
>
</el-select>
</section>
</template>
<script>
export default {
name: "Users",
props: {
users: { type: Array, required: true },
// 传入值
code: "",
// 传入文本
text: { type: String, default: "" },
// 单选多选
isMul: { type: Boolean, default: false },
// 是否不可用
disabled: { type: Boolean, default: false },
// 是否不可用
readonly: { type: Boolean, default: false },
// 是否不填/选
isRequire: { type: Boolean, default: false },
// 是否可清除选项
clearable: { type: Boolean, default: true },
// 是否可过滤选项
filterable: { type: Boolean, default: false },
// 如:视图中配置:code="formField.genderCode",则codeField="genderCode"
codeField: { type: String, default: "" },
// 获取组件中的名称,如:textField="genderName"
textField: { type: String, default: "" },
// 下拉选项
options: {
type: Array,
default: function () {
return [];
},
},
// 传入绑定值/文本字段名称,格式:值字段名称,文本字段名称,如:genderCode,genderName
oFields: { type: String, default: "" },
},
data() {
return {
defOptionFields: ["myValueCode", "myValueName"],
// 绑定数据对象字段(两个值:[val,txt])
optionFields:
this.oFields && this.oFields.indexOf(",") > -1
? this.oFields.split(",")
: [],
placeholder:
this.showPlaceholder === null ? "请输入" : this.showPlaceholder,
modelCode: this.code,
// 绑定传入文本并同步界面数据
modelText: this.text,
// 下拉选项数据
optionDatas: this.options || [],
};
},
mounted() {
this.optionDatas = [
{
myValueCode: "0",
myValueName: "女",
},
{
myValueCode: "1",
myValueName: "男",
},
];
},
methods: {
sendCode1(value) {
if (this.modelCode === null) {
this.modelCode = this.isMul === false ? "" : [];
}
var code =
this.isMul === false ? this.modelCode : this.modelCode.join(",");
var text = "";
if (code === null || code === undefined) {
code = "";
}
let valField = "";
let txtField = "";
// 返回值、文本 优先读取optionFields/defOptionFields,再读取codeField/textField
if (this.optionFields.length > 1) {
valField = this.optionFields[0];
txtField = this.optionFields[1];
} else if (this.defOptionFields && this.defOptionFields.length > 1) {
valField = this.defOptionFields[0];
txtField = this.defOptionFields[1];
}
if (valField === "") {
valField = this.codeField;
txtField = this.textField;
}
let selectData = [];
var arr = this.isMul === false ? code.split(",") : code;
selectData = this.optionDatas.filter(
(o) => arr.indexOf(o[valField]) > -1
);
if (selectData && selectData.length > 0) {
for (var i = 0; i < selectData.length; i++) {
text += selectData[i][txtField];
if (i < selectData.length - 1) {
text += ",";
}
}
}
this.$emit("changeCode", code, text, this.codeField, this.textField);
},
clearCodeSelect() {
this.sendCode1();
},
},
};
</script>