工程化的开发方式
这是开发中、大型项目的必备技能,网上资料也很多,这里只是一个简单的综合性的介绍。包括vue的全家桶、建立项目的几种方式、UI库的简单使用等。 可以和上一篇的cnd方式做项目做一下对比。
node.js,npm、cnpm、yarn
node.js
执行 npm run serve ,然后就可以在浏览器里面访问了,那么这是怎么做到的呢? 这个就要归功于node了。建立项目的时候,会自动创建一个node的服务,这样我们就可以边写代码,边看运行效果了。 所以工程化开发,首先要安装一个node。安装方法网上已经有很多了,这里就不搬运了。 大家也不用担心,不会用node怎么办。这个是自动化的,记住几个命令就行。
然后要掌握一个安装包的技能,npm、cnpm、yarn都是包管理的工具。
npm
因为需要从国外服务器下载需要的文件,所以安装包的速度会很慢。如果不发布自己的包的话,那么就没有必要用这个了。 安装node后,一般会自动安装npm。
cnpm
是淘宝团队做的一个国内镜像,cnpm会从国内服务器下载需要的文件,所以速度就非常快了,除了不能发布包之外,其他功能和npm是一样的。
- 安装方式:
npm install -g cnpm --registry=https://registry.npm.taobao.org 复制代码
yarn
Yarn是facebook发布的一款取代npm的包管理工具。 yarn会缓存下载的文件,虽然第一次会有点慢,但是以后就会非常快了,而且还可以并行下载。所以推荐使用 yarn 做资源包的管理工具。
- 安装方式:
npm install -g yarn 复制代码
- 使用方式
yarn --version // 查看版本 yarn init // 同npm init,执行输入信息后,会生成package.json文件 yarn add [package] // 在当前的项目中添加一个依赖包,会自动更新到package.json和yarn.lock文件中 yarn upgrade // 用于更新包到基于规范范围的最新版本 yarn install //安装package.json里所有包,并将包及它的所有依赖项保存进yarn.lock yarn serve // 开发环境下运行vue3的项目 yarn publish // 发布包 yarn remove [package] // 移除依赖包 复制代码
也可以到官网下载安装:yarn.bootcss.com/docs/instal…
安装Vue
# 最新稳定版 yarn add vue@next # OR cnpm install vue@next 复制代码
安装脚手架
yarn global add @vue/cli@next # OR npm install -g @vue/cli@next 复制代码
建立项目
目前有两种方式创建Vue3的项目:
- 传统的脚手架(cli)的方式,完善、全面、稳定、成熟。
- 新的vite的方式,似乎还在完善中,可以尝尝鲜。
cli 脚手架的方式建立项目
官网:cli.vuejs.org/zh/guide/其优点就是可以自动创建项目目录结构和需要的各种文件,免去新手自己安装各种包的麻烦。 vue全家桶、Babel/TypeScript 转译、ESLint 集成、单元测试和 end-to-end 测试等。 网上资料比较多,我就不搬运了。
vue create my-project // 命令行的方式创建项目,按照提示一步一步选择,最后创建项目。 # OR vue ui // 可以在浏览器里面可视化的方式创建项目,而且是中文版,适合新手使用。 复制代码
vite 的方式建立项目
vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方法,它允许快速提供代码。通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。 这是尤雨溪大大做的一个新的方式,想法非常新颖,可以多关注和尝试。
$ npm init vite-app <project-name> $ cd <project-name> $ npm install $ npm run dev 复制代码
或者
$ yarn create vite-app <project-name> $ cd <project-name> $ yarn $ yarn dev 复制代码
一个有趣的现象,在vue的官网上面,vite建立项目的方法,直接介绍了,但是cli建立项目的方法却没有直接介绍,而是加了一个不太明显的连接,害得我都没看到。
记得以前是在官网里直接介绍cli的创建项目的方式的。 那么是不是意味着vue打算主推vite呢?
vue全家桶的手动安装方式
- Router
npm install vue-router # or yarn add vue-router 复制代码
- Vuex
npm install vuex --save # or yarn add vuex 复制代码
安装第三方UI库
- element Plus
npm install element-plus --save 复制代码
- Ant Design Vue
npm install ant-design-vue --save yarn add ant-design-vue 复制代码
- Vant
npm i vant@next -S 复制代码
其他略...
项目结构
好了,各种折腾,终于把项目搭建起来了,我们来看看是什么样子
是不是很简单清晰。
代码入口 main.js
import { createApp } from 'vue' // 引入 createApp 函数 import Antd from 'ant-design-vue' // 引入UI库 import 'ant-design-vue/dist/antd.css' // 引入css import App from './App.vue' // 引入我们写的代码 import router from './router' // 引入路由的实例 import store from './store' // 引入状态管理的实例 createApp(App) .use(store) // 状态管理 .use(router) // 路由 .use(Antd) // UI 库 .mount('#app') // 挂载 复制代码
- import
es6的一种加载方式,from 后面只能写常量,不能写变量,也不支持字符串的运算。
还是感觉cdn的方式更容易看清楚内部原理。
页面入口 App.vue
在vue里面都是组件(.vue),只是我们从业务逻辑的角度来说,可以分为页面和组件两种,当然并不是严格的区分。
App.vue 可以视为页面的入口
<template> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <router-view/> </template> <script> export default { name: 'App', setup() { console.log('你好,世界!') } } </script> <style lang="scss"> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; a { font-weight: bold; color: #2c3e50; &.router-link-exact-active { color: #42b983; } } } </style> 复制代码
脚手架默认为我们做了一个简单的路由,设置了模板、代码、css的结构。
- template
模板部分。可以写html和vue的方式。
- script
js脚本部分,可以没有。支持js语法,写vue需要的各种代码。
- style
css部分,也可以没有。
页面 About.vue
在这里实现一下上一篇里的功能。
- 模板部分
<template> <div class="about"> <h1>这是一个测试页面</h1> {{value}}<br> <input type="button" value="测试" @click="click"/> <hr> vuex状态演示<br> $store - count:{{$store.state.count}}<br> $store - myObject:{{$store.state.myObject}}<br> $store - myObject.time:{{$store.state.myObject.time}}<br> setup - count:{{count}}<br> setup - obj :{{obj}}<br> setup - objTime :{{objTime}}<br> <input type="button" @click="setCount" value="vuex的 计数"/><br> <input type="button" @click="setTime" value="vuex的 设置属性"/><br> <hr> 路由的演示<br> <div> <p> 路由的简单演示,其实CND方式不太适合用路由,因为组件写起来比较麻烦。<br> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/about/home">首页</router-link> <router-link to="/about/product">产品</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> 路由入口<br> <router-view></router-view> </div> </div> </template> 复制代码
按照前一篇的例子,实现相同的功能,做一下对比,可以发现基本没有啥区别。
- js代码部分
<script> import { ref } from 'vue' import { useStore } from 'vuex' // vue3的 Composition API 的含义 const testManage = () => { const value = ref ('你好,世界') const click = () => { value.value = '好的,收到' + new Date().valueOf() } return { value, click } } export default { name: 'Home', setup() { // 使用外面的定义,分解setup内部的代码 const { value, click } = testManage() const store = useStore() console.log('store', store) console.log('store.state', store.state) const setCount = () =>{ store.commit('setCount') } const setTime = () =>{ store.commit('setTime') // 测试直接修改 // 加上 readonly 就不可修改了, // 但是代码并不会报错 setTimeout(() => { obj.time = '222' console.log('setTimeout-obj',obj) },500) } // 获取state // const count1 = store.state.count 强烈建议不要直接访问 const count = store.getters.getCount const obj = store.getters.getMyObject const objTime = store.getters.getTime console.log('obj', obj) console.log('objTime', objTime) return { // 返回给模板,否则模板访问不到。 value, click, setCount, setTime, count, obj, objTime } } } 复制代码
基本上也没啥大区别。不重复介绍了。
组件
- home.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> home <br> $store - count:{{$store.state.count}}<br> $store - myObject:{{$store.state.myObject}}<br> </div> </template> <script> export default { name: 'com-home', props: { msg: String } } </script> 复制代码
基本上是一个空的组件,没啥实际内容,只是显示一下状态管理里的state的数据。只是一个简单的演示。 另一个组件也是类似,就不贴代码了。
状态管理
import { readonly } from 'vue' import { createStore } from 'vuex' export default createStore({ state: { count: 0, myObject: { time: '现在的时间' } }, getters: { getCount: (state) => { return state.count }, getMyObject: (state) => { return readonly(state.myObject) }, getTime: (state) => { return state.myObject.time } }, mutations: { setCount(state) { state.count++ }, setTime(state) { state.myObject.time = '现在时间:' + new Date() } }, actions: { }, modules: { } }) 复制代码
对比一下cnd的方式,除了引用的部分之外,其他的也是基本一致。不再次介绍了。
路由设置
import { createRouter, createWebHistory } from 'vue-router' import Home from '../views/Home.vue' const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import('../views/About.vue'), children: [ { path: 'home', name: 'About-home', component: () => import('../components/home.vue') }, { path: 'product', name: 'About-product', component: () => import('../components/product.vue') } ] }, ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default router // 返回实例 复制代码
脚手架默认设置了一个简单路由,这个就不改了,只是在about里面加一个子路由,实现一个简单的嵌套路由。
主要部分都介绍完毕。
小结
工程化开发的好处有很多,比如可以就帮我们划分好目录结构,文件位置,这样大家都按照这个规则来开发,那么看别人的项目的时候就不用费劲想别人会用什么开发方式了。
这只是做开发的第一步,后面还有很多很多很多。。。