尚硅谷谷粒商城

MAC环境搭建

#1. 软件准备

下载、安装Virtual Box https://www.virtualbox.org/wiki/Downloads

下载、安装Vagrant https://www.vagrantup.com/downloads.html

2. vagrant:查看是否安装成功

3. vagrant init centos/7:初始化

> 这里有各种 Linux 镜像 https://app.vagrantup.com/boxes/search,选择自己需要的版本下载即可
>
> 初始化后,在当前用户文件夹下会有一个 Vagrantfile 文件

4. vagrant up:启动虚拟机

(第一次运行会下载)

vagrant 下载很慢
使用迅雷下载,然后执行

vagrant init centos7 https://mirrors.ustc.edu.cn/centos-cloud/centos/7/vagrant/x86_64/images/CentOS-7.box
//vagrant box add centos/7 /Users/taylor/personal/setups/CentOS-7-x86_64-Vagrant-1905_01.VirtualBox.box

然后再执行 vagrant up即可,启动完成看到下面的内容,就可以愉快的vagrant ssh登录了

5.修改VB网络地址

1创建一个网卡

2修改Vagrantfile,使在一个网段,比如改成56.10

然后宿主机和虚拟机互ping通即可

ping -c 3 xxx.xxx.xxx.xxx

docker

设置云源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

卸载docker

su root
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

安装依赖

sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

安装
sudo yum install docker-ce docker-ce-cli containerd.io

sudo systemctl start docker
sudo docker images

加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-‘EOF’
{
“registry-mirrors”: [“https://x6vry1mr.mirror.aliyuncs.com”]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart dockerdocker ps

开机启动
systemctl start docker
systemctl enable docker

6.docker 安装mysql

  sudo docker pull mysql:5.7docker run -p 3306:3306 --name mysql \-v /mydata/mysql/conf:/etc/mysql/ \-v /mydata/mysql/log:/var/log/mysql \-v /mydata/mysql/data:/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=root \-d mysql:5.7

vi /mydata/mysql/conf/my.cnf

[client]
default-character-set = utf8[mysql]
default-character-set = utf8[mysqld]
init_connect=' SET collation_connection = utf8_unicode_ci'
init_connect=' SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

docker restart mysql
docker exec -it mysql /bin/bash

自启动 docker update mysql --restart=always

7.docker 安装redis

docker pull redismkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.confdocker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf

客户端 docker exec -it redis redis-cli

持久化aof
vi redis.conf
appendonly yes

重名 You have to remove (or rename) that container to be able to reuse that name
docker ps -a
去重exited docker rm 5e9b198b3dcb # 删除失效容器

reids镜像

基础配置
jdk1.8 maven的下载http://maven.apache.org/ 本地仓库MavenRepository
E:/ideaMaven/MavenRepository
镜像

  alimaven
  central
  aliyun maven
  http://maven.aliyun.com/nexus/content/groups/public/

环境变量path 增加maven的bin路径
idea配置maven

idea插件lombok mybatisx

vss插件vetur、javas、html css、auto close、auto rename、chinese、eslint、live server、open in

码云git配置

git客户端 git-scm.com
初次运行 Git 前的配置 git-bash
设置Git的user name和email:

$ git config --global user.name "zanyang"$ git config --global user.email "zanyang@gmail.com"

2.生存密钥:

$ ssh-keygen -t rsa -C “******.com”

按3个回车,密码为空。

Your identification has been saved in /home/tekkub/.ssh/id_rsa.Your public key has been saved in /home/tekkub/.ssh/id_rsa.pub.The key fingerprint is:………………

最后得到了两个文件:id_rsa和id_rsa.pub
cat ~/.ssh/id_rsa.pub
复制到码云的设置ssh公钥
ssh -T git@gitee.com测试是否成功
仓库 生产开发模型 maven模板
idea新建项目到git

3.添加密钥到ssh:ssh-add 文件名

$ ssh-add ~/.ssh/id_rsa

需要之前输入密码。

4.在github上添加ssh密钥,这要添加的是“id_rsa.pub”里面的公钥。

打开https://github.com/,登陆,然后添加ssh。

5.测试:ssh git@github.com

The authenticity of host ‘github.com (207.97.227.239)’ can’t be established.RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added ‘github.com,207.97.227.239′ (RSA) to the list of known hosts.ERROR: Hi tekkub! You’ve successfully authenticated, but GitHub does not provide shell accessConnection to github.com closed.

三、 开始使用github

1.获取源码:

$ git clone git@github.com:billyanyteen/github-services.git

2.这样你的机器上就有一个repo了。

3.git于svn所不同的是git是分布式的,没有服务器概念。所有的人的机器上都有一个repo,每次提交都是给自己机器的repo

仓库初始化:

git init

生成快照并存入项目索引:

git add

文件,还有git rm,git mv等等…

项目索引提交:

git commit

4.协作编程:

将本地repo于远程的origin的repo合并,

推送本地更新到远程:

git push origin master

更新远程更新到本地:

git pull origin master

补充:

添加远端repo:

$ git remote add upstream  你的git地址

开发环境

maven配置

1、Maven

(1)使用阿里镜像仓库

<!-- 阿里镜像仓库-->
<mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public/</url><mirrorOf>central</mirrorOf>
</mirror>

(2)使用jdk1.8编译

<profile>
<id>jdk‐1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

搭建工程
添加模块
配置.ignore

在gitee上创建仓库,并且在IDEA中clone,并创建member会员服务,ware仓储服务,order订单服务,product产品服务,coupon优惠券服务,修改.gitignore文件,增加以下内容忽略这些文件的修改。

数据库设计

Mac上的数据库设计工具
DBeaver

Docker上开机启动
sudo docker update mysql --restart=always

renren-fast数据库

1.git clone下载renren-fast, renren-fast-vue,renren-generator仓库代码

https://gitee.com/renrenio/renren-fast.githttps://gitee.com/renrenio/renren-fast-vue.gihttps://gitee.com/renrenio/renren-generator.git  这个

2.将renren-fast代码放到gulimall工程目录下面,并在总工程的pom.xml引入renren-fast module.

3.执行renren-fast模块种的db文件下的mysql.sql语句

注意,创建的数据库的基字符集使用utf8mb4。

4.修改renren-fast的application-dev.yml语句中的如下信息

url: jdbc:mysql://172.0.1.xx:3306/gulimall_admin
username: root
password: 123456
  1. generator.properties 修改mainpath和包名package和模块名product和表前缀pms_
  2. 生成代码不要shiro(template中注释requirespermissions) 复制粘贴到微服务中 删除前端代码view
  3. 从renren-fast中拿公共类到自己的common公共类中,所有微服务依赖他
  4. 依赖mybatis-plus、lombok、R、httpcomponents
  5. 依赖mysql-connector-java、servlet-api(provided</>)
  6. 复制RRexception yml中配置数据源和mapper的路径mapper-locations和启动类中的mapperscan
  7. 自增主键global-config id-type:auto
  8. list d querywrapper.eq(cloum:“”).list.foreach((item)->{…})

启动renren-fast应用

注意,这里遇到一个错误,就是application-dev.yml文件中的com.alibaba.druid.pool.DruidDataSource 显示红色,出错。
另外,一个就是RenrenApplication.java中String标红,显示需要导入包。原来是这个module没有设置对应的jdk,设置一下jdk8就没问题了。

前端环境准备

5.安装Node.js,配置npm使用淘宝镜像

npm config set registry http://registry.npm.taobao.org/

npm config set registry http://registry.npm.taobao.org/

报错

gyp: No Xcode or CLT version detected!
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/Users/arproject/renren-fast-vue/node_modules/node-gyp/lib/configure.js:345:16)
gyp ERR! stack at ChildProcess.emit (events.js:311:20)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
gyp ERR! System Darwin 19.3.0
gyp ERR! command "/usr/local/bin/node" "/Users/arproject/renren-fast-vue/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /Users/arproject/renren-fast-vue/node_modules/node-sass
gyp ERR! node -v v12.16.1
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok

https://zhuanlan.zhihu.com/p/105526835

6.用vscode打开renren-fast-vue代码,在终端执行:npm install 下载安装依赖,
如果下载出错,可以使用cnpm install 下载,在下载完成后,执行:npm run dev 启动

7.renren-generator代码导入到我们的项目,并启动

8.使用renren-generator结合renren-fast-vue,根据数据库,反向生成product模块代码,并把main文件copy覆盖product下面的main文件夹。

9…新建gulimall-common模块,把公共的API等信息放到common模块中,并解决product中代码引用包的问题。

10.如法炮制,依次使用人人开源产生代码,覆盖main,并导入gulimall-common这类。

11.使用MyBatis-Plus,测试数据库读写问题

(1)导入依赖,在gulimall-common模块的pom.xml中加入:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version>
</dependency>

(2)在gulimall-product的application.yml文件增加以下内容:

spring:datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.xx:3306/gulimall_pms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
#driver-class-name: com.mysql.jdbc.Drivermybatis-plus:mapper-locations: classpath*:/mapper/**/*.xmlglobal-config:
db-config:id-type: auto

(3)在GulimallProductApplicationTests.java中,如下:

@SpringBootTest
class GulimallProductApplicationTests {
@Autowired
BrandService brandService;@Test
void contextLoads() {
//BrandEntity brandEntity = new BrandEntity();
//brandEntity.setBrandId(4L);
//brandEntity.setDescript("华为");//brandEntity.setName("华为");
//brandService.save(brandEntity);
//System.out.println("保存成功...");//brandService.updateById(brandEntity);List<BrandEntity> list = brandService.list(new QueryWrapper<BrandEntity>().eq("brand_id", 4L));
list.forEach((item) -> {
System.out.println(item);
});
}}

(4)启动GulimallProductApplicationTests方法,依次测试上面的save方法,update方法,以及遍历方法,可以看到数据库中的数据是正确的。

(5)使用总结

/*1、整合MyBatis-Plus(1)、导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>(2)、配置
1、配置数据源
1)、导入数据库的驱动
2)、在application.yml配置数据源相关信息
2、配置Mybatis-Plus
1)、使用MapperScan
2)、告诉MyBatis-Plus,sql映射文件位置*/

注意,这里有两个问题:
(1)启动整个测试类,application.yml中的driver-class-name: com.mysql.jdbc.Driver 提示报警,应该使用driver-class-name: com.mysql.cj.jdbc.Driver
(2)数据库写入出现乱码,应该把application.yml中的url改为:
url: jdbc:mysql://172.0.1.xx:3306/gulimall_pms?characterEncoding=UTF-8

至此,整个项目基本环境已经弄好了。

1.安装xcode

2.删除node_modules

3.删除高版本nodejs,安装10.X版本,10.19.0是没问题的

sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man//node.}

4.npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver

5.npm install

代码生成器

80端口被占用
sudo lsof -n -P | grep :80

sudo apachectl stop

谷粒框架

Nacos配置启动

common中
1.SpringCloudAlibaba版本引用

在gulimall-common的pom.xml文件中引入spring-cloud-alibaba,如下:

<dependencyManagement>
<!-- spring cloud alibaba 2.1.0.RELEASE -->
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

2.引入Alibaba Nacos注册中心

配置参考:https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md

(1)引入Nacos Discovey,在gulimall-common的pom.xml文件中加上以下内容:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

(2)下载Nacos server,我下载的是1.1.4版本,解压后,执行bin目录下面的startup.cmd文件启动。

(3)在应用中配置指定Nacos server注册中心地址,以gulimall-coupon模块说明,在application.yml文件中添加如下内容:

spring:cloud:nacos:discovery:server-addr: 127.0.0.1:8848
application:name: gulimall-coupon

(4)使用@EnableDiscoveryClient注解开启服务注册于发现功能

(5)启动gulimall-coupon服务(注意Nacos Server要先启动),访问本地连接:http://localhost:8848/nacos/#/serviceManagement?dataId=&group=&appName=&namespace=,会看到服务列表里面出现gulimall-coupon

3.在gulimall-member远程调用gulimall-coupon模块的服务

(1)openfeign声明式远程调用引入,在gulimall-member模块的pom.xml文件加入以下内容:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2)在CouponController.java加上远程调用的方法实现

@RequestMapping("/member/list")
public R membercoupons() {
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100减50");
return R.ok().put("coupons", Arrays.asList(couponEntity));
}

(3)在gulimall-member模块下,建立一个接口CouponFeignService.java,并写上上面实现的远程调用的API。

package com.atguigu.gulimall.member.feign;import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;/*** 这是一个声明式的远程调用*/
@FeignClient("gulimall-coupon")
public interface CouponFeignService {@RequestMapping("/coupon/coupon/member/list")
public R membercoupons();
}

(4)在GulimallMemberApplication.java中添加@EnableFeignClients(basePackages = “com.atguigu.gulimall.member.feign”) ,这个注解的作用是让springcloud扫描com.atguigu.gulimall.member.feign包下的所有接口

/*** 1、想要远程调用别的服务* 1)、引入open-feign* 2)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务*  1、声明接口的每一个方法都是调用哪个远程服务的那个请求* 3)、开启远程调用功能*/
@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallMemberApplication {public static void main(String[] args) {
SpringApplication.run(GulimallMemberApplication.class, args);
}}

(5)在gulimall-member模块下的controller数据包写一个测试方法来调用这个远程服务API,比如:在MemberController.java中写一个测试方法,如下:

@Autowired
CouponFeignService couponFeignService;@RequestMapping("/coupons")
public R test() {
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("张三");R membercoupons = couponFeignService.membercoupons();
return R.ok().put("member", memberEntity).put("coupons", membercoupons.get("coupons"));
}

(6)启动gulimall-coupon和gulimall-member这两个微服务,访问测试API的地址:http://localhost:8000/member/member/coupons,即可以看到能访问到数据。

4.引入Alibaba Nacos配置中心
group(开发,测试、生产)–namespace(微服务)–ext-config dataid(mybatis等配置)refresh=true

参考地址:https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md

(1)导入Nacos配置中心,在gulimall-common的pom.xml文件中加上以下内容:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>

(2)gulimall-coupon模块西安的resource目录下新建文件bootstrap.properties,内容如下:

spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

(3)在gulimall-coupon模块下的application.properties中加入以下配置:

coupon.user.name=zhangsan
coupon.user.age=18

(4)写测试方法,在CouponController.java中加入以下内容:

@Value("${coupon.user.name}")
private String name;@Value("${coupon.user.age}")
private Integer age;@RequestMapping("/test")
public R test() {return R.ok().put("name", name).put("age", age);
}

(5)启动coupon服务,访问链接:http://localhost:7000/coupon/coupon/test,即可以看到上面的配置
(6)但是,这种方法有一个问题,就是如果配置改变了,需要修改application.properties,并重启coupon微服务,这是个不好的,所以我们引入了Nacos配置中心。根据启动log,微服务可以从nacos读取配置文件信息,默认的是:gulimall-coupon.properties。
(7)在http://localhost:8848/nacos的配置列表中,新建配置,Data Id为:gulimall-coupon.properties,规则就是,应用名.properties,在里面添加任意配置内容,比如:

coupon.user.name=zhangsan2
coupon.user.age=24

(8)在上面的test()方法所在的类上标注@RefreshScope,这样,当Nacos配置中心的gulimall-coupon.properties配置内容修改了,微服务就可以动态的获取到最新的配置信息,并且,这个优先级是高于微服务本身的配置的。
(9)使用Nacos作为配置中心的使用总结如下:

/*** 1、如何使用Nacos作为配置中心统一管理配置*  1)、引入依赖*  <dependency>*  <groupId>com.alibaba.cloud</groupId>*  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>*  </dependency>*  2)、创建一个bootstrap.properties,内容如下:*  spring.application.name=gulimall-coupon*  spring.cloud.nacos.config.server-addr=127.0.0.1:8848*  3)、需要给配置中心添加一个叫 数据库集(Data Id)gulimall-coupon.properties,默认规则:yingyongming.properties*  4)、给应用名.properties添加任何配置*  5)、动态获取配置。*  @RefreshScope:动态获取并刷新配置*  @Value("${配置项的名}"):获取到配置*  如果配置中心和当前应用的配置文件都配置了相同的项,优先使用配置中心的配置**/

5.Nacos作为配置中心的更多细节用法
(1)为了区分配置和隔离,Nacos引入了几个概念:

命名空间,用作配置隔离,默认:public(保留空间):默认新增的所有配置都在public空间,开发,测试,生产:利用命名空间来做环境隔离,或者,每一个微服务之间相互隔离配置,每个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置。
配置集以及配置ID,配置集就是所有配置的集合,配置集ID类似文件名,也就是Nacos 中的Data ID。
配置分组,默认所有的配置分组都属于:DEFAULT_GROUP,当然,也指定自己的配置分组,比如1111双十一,618之类的。
在之前已经提到,在默认public命名空间,以及使用默认的分组DEFAULT_GROUP里面,创建Data ID:gulimall-coupon.properties,然后在bootstrap.properties文件里面添加指定Nacos的地址,就可以访问默认的gulimall-coupon.properties里面的配置信息了,这个是默认的规则。

但是,如果我们想要用自己的,不是default默认的配置怎么处理呢?

比如还是gulimall-coupon.properties这个Data ID,但是放在了另外一个命名空间,比如是coupon(对应微服务模块的名称,可以每个微服务建立一个对应的命名空间),而且放在了一个prod分组里面(类似的,同一个coupon命名空间下面,还可以建立dev分组,test分组等),那么如何在微服务里面指定访问这个配置呢?答案是:在bootstrap.properties里面添加指定对应的namespace和group,如下:

spring.application.name=gulimall-couponspring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=9bc589c6-3f38-470b-af8d-fe84f04770ef
spring.cloud.nacos.config.group=prod

9bc589c6-3f38-470b-af8d-fe84f04770ef是Nacos上coupon命名空间对应的ID值。prod则对应prod这个配置分组,这样,当微服务启动时,如果要获取的配置在Nacos配置中心有(也就是这里的gulimall-coupon.properties)的话,那么就优先使用配置中心的,否则,就会使用代码中application.properties文件的配置。

(2)同时加载多个配置(新的知识点)
注意一下,我们之前是把所有的配置都放在了application.yml中,比如:

spring:datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.172:3306/gulimall_sms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Drivercloud:
nacos:discovery:
server-addr: 127.0.0.1:8848application:
name: gulimall-couponmybatis-plus:mapper-locations: classpath*:/mapper/**/*.xmlglobal-config:
db-config:id-type: autoserver:port: 7000

但是,如果配置很多的话,都同在同一个文件中的话,不好看,也不便于配置,所以,建议按照不同的作用写到几个配置文件中,而微服务也会从Nacos配置文件中读取配置,并且Nacos也支持多配置文件读取,那么怎么配置使用呢?
在上面我们提到了新建了coupon这个命名空间对应gulimall-coupon这个模块,那么我们把上面的application.yml配置按照不同的功能,拆分为三个配置文件配置到Nacos中,放在coupon命名空间,dev配置分组下面,它们分别是:datasource.yml,内容如下:

spring:datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.xx:3306/gulimall_sms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver

mybatis.yml文件,内容如下:

mybatis-plus:mapper-locations: classpath*:/mapper/**/*.xmlglobal-config:
db-config:id-type: auto

以及other.yml,内容如下:

spring:cloud:
nacos:discovery:
server-addr: 127.0.0.1:8848application:
name: gulimall-coupon


server:
port: 7000
而使用的话,很简单,在上面bootstrap.properties文件的基础上增加一下内容:

spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=truespring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=truespring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true

分别制定要导入的配置名称,所在的配置分组group,已经是否动态刷新(refresh)。
最好,把application.yml中的配置全部注释掉,启动coupon微服务,来验证配置。可以发现,微服务能够正常读取Nacos中的这三个配置文件。
对于这两部分内容,总结起来就是:

/*** 1、如何使用Nacos作为配置中心统一管理配置*  1)、引入依赖*  <dependency>*  <groupId>com.alibaba.cloud</groupId>*  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>*  </dependency>*  2)、创建一个bootstrap.properties,内容如下:*  spring.application.name=gulimall-coupon*  spring.cloud.nacos.config.server-addr=127.0.0.1:8848*  3)、需要给配置中心添加一个叫 数据库集(Data Id)gulimall-coupon.properties,默认规则:yingyongming.properties*  4)、给应用名.properties添加任何配置*  5)、动态获取配置。*  @RefreshScope:动态获取并刷新配置*  @Value("${配置项的名}"):获取到配置*  如果配置中心和当前应用的配置文件都配置了相同的项,优先使用配置中心的配置** 2、细节*  1)、命名空间,配置隔离*  默认:public(保留空间):默认新增的所有配置都在public空间*  1、开发,测试,生产:利用命名空间来做环境隔离* 注意,在bootstrap.properties 配置上,需要使用哪个命名空间下的配置。* spring.cloud.nacos.config.namespace=32c4a90d-6ac4-4f04-b050-e09bbe7bd58f*  2、每一个微服务之间相互隔离配置,每个微服务都创建自己的命名空间,只加载自己命名空间下的所 * 有配置**  2)、配置集:所有配置的集合**  3)、配置集ID:类似文件名*  Data ID: 类似文件名**  4)、配置分组:*  默认所有的配置集都属于:DEFAULT_GROUP*  1111,618**  每个微服务创建自己的命名空间,使用配置分组区分环境,dev、test、prod**  3、同时加载多个配置文件*   1)、微服务任何配置信息,任何配置文件都可以放在配置中心中*   2)、只需要在bootstrp.properties说明加载配置中心那些配置文件即可*   3)、@Value、@ConfigurationProperties...*   以上SprintBoot任何方法从配置文件中获取值,都能使用*   配置中心有的优先使用配置中心中的**/

6.SpringCloud Gateway网关
(1)Gateway网关简单介绍
网关作为流量的入口,常用功能包括路由转发、权限校验、流量控制等,而SpringCloud gateway作为SpringCloud官方推出的第二代网关框架,取代了Zuul网关。
简单一句话总结:先断言(判断请求是否符合某个路由规则),(如果符合了某个路由规则)再路由到指定地方,但在路由之前要先过滤。

官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/

(2)引入gulimall-gateway模块
断言(工厂类)-路由-过滤(工厂类)
排除mybatis springbootapplication(exclude = {datasourceautoconfig})
新建gulimall-gateway模块,用Spring Initaliz的方法,并导入gateway模块,建好后,在pom.xml中导入gulimall-common的模块依赖。

<dependency><groupId>com.atguigu.gulimall</groupId><artifactId>gulimall-common</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

gulimall-gateway模块,同样需要注册到Nacos注册中心和配置中心,下面先弄注册到Nacos注册中心的配置,需要在application.properties文件中指定Nacos注册中心的地址

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=gulimall-gateway
server.port=88

而要使用Nacos配置中心,需要在bootstrap.properties文件中指定Nacos配置中心的地址:

spring.application.name=gulimall-gatewayspring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=7df3fe8a-4e08-46d5-8535-da50e6834bfb

这里的7df3fe8a-4e08-46d5-8535-da50e6834bfb是指Nacos配置中心的gateway命名空间所对应的ID。

最后,在application.yml中写上gateway使用的配置规则,比如路由,断言,过滤等。比如:

spring:cloud:
gateway:routes:- id: test_routeuri: https://www.baidu.compredicates:- Query=url,baidu- id: qq_routeuri: https://www.qq.compredicates:- Query=url,qq

访问:http://localhost:88/hello?url=qq,就会转到这qq个url地址:https://www.qq.com/hello,同样的,访问:http://localhost:88/hello?url=baidu,就会转到百度的url地址.

至此,关于的SpringCloud Alibaba的基本使用告一段落。

报错
https://juejin.im/entry/5cd39b4de51d453a59418b8e

删除报错信息中的’/data/nacos/data/derby-data’目录,重新启动。

注册中心 服务发现

1.添加pom依赖
放在gulimall-common中,作为公共服务

<!--服务注册/发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2.在application.yml中添加nacos配置

3.将服务注册的注册中心

配置中心
com.atguigu.gulimall.coupon.GulimallCouponApplication

* 一、如何使用nacos作为配置中心统一管理配置* 1.在common中引入依赖*<dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>*</dependency>* 2.创建配置文件 bootstrap.properties*    spring.application.name=gulimall-coupon*  spring.cloud.nacos.config.server-addr=192.168.0.100:8848* 3.在nacos客户端,给配置中心添加一个数据集*  gulimall-coupon.properties*  格式为 应用名称.properties** 4.在 应用名称.properties中添加所需要的配置* 5.动态获取配置*  添加注解*   @RefreshScope:动态刷新并获取配置*    @Value("${配置项名称}")**     如果配置中心和当前应用的配置文件中配置了相同的配置项,优先使用配置中心的配置** 二、细节* 1.命名空间:作用 做配置隔离*   默认:public(保留空间);默认新增的所有配置都在public空间内*   ①开发、测试、生产 分别配置*   在bootstrap.properties里配置想要使用的命名空间的配置项*   spring.cloud.nacos.config.namespace=8a4f21ba-3ef2-4754-8b2f-ef3b3c2ed8c8*   ②每一个微服务之间相互隔离,每一个微服务创建自己的命名空间,只加载自己命名空间下的所有配置* 2.配置集* 3.配置集ID* 4.配置分组** 一般实践:* 每个微服务创建自己的命名空间,使用配置分区区分环境:dev、test、prod

命名空间

1在nacos界面添加新命名空间
2默认使用public命名空间
3修改使用命名空间

Feign远程调用

com.atguigu.gulimall.member.GulimallMemberApplication

调用方

com.atguigu.gulimall.member.controller.MemberController



服务方

com.atguigu.gulimall.coupon.controller.CouponController

网关
性能对比

引入common时排除数据库相关

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

报错
spring initializr error
取消代理即可

包冲突

网上查是gateway和web包冲突,解决方案:common的pom替换掉

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>gulimall</artifactId>
<groupId>com.atguigu.gulimall</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>gulimall-common</artifactId>
<description>每一个微服务公共的依赖,bean,工具类等</description><dependencies>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency><dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency><!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>

commons-lang
commons-lang
2.6

<!--导入mysql驱动-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency><dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency><!--服务注册/发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency><!--配置中心来做配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency><dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

路由示例

前端学习

网关路由与路径重写
跨域问题
端口及之前的内容【协议、域名、端口】有任何不同,就不允许获取数据

解决方案
通过Nginx反向代理,转化为同一个域

通过gateway的filter

一、前端技术栈类比

JavaScript  es6,7,8  —— Java jdk9,10,11…

框架 JQuery、Vue、React —— 框架 Spring、SpringMVC

工具 webstorm、vscode —— 工具 idea、eclipse

项目构建 webpack、gulp —— 项目构建 maven、gradle

依赖管理 npm —— 依赖管理 maven

二、ES6

1、ES6简介

ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015).是JavaScript语言的下一代标准,每年一个版本,企业级开发语言。

ECMAScript是浏览器脚本语言的规范,而各种我们熟知的js语言,如JavaScript则是规范的具体实现。

2、ES6新特性学习

(1)var声明的变量往往会越狱,let声明的变量有严格局部作用域

<script>
// var 声明的变量往往会越狱
// let 声明的变量有严格局部作用域
{
var a = 1;
let b = 2;
}
console.log(a); //1
console.log(b); //ReferenceError: b is not defined
</script>

(2)var可以声明多次,let只能声明一次

//var可以声明多次,let只能声明一次
var m = 1
var m = 2
let n = 3
let n = 4
console.log(m) // 2
console.log(n) //Identifier 'n' has already been declared

(3)var会变量提升,let不存在变量提升

console.log(x); //undefined
var x = 10;
console.log(y) //ReferenceError: Cannot access 'y' before initialization
let y = 20;

(4)const声明常量(只读常量)

//const声明常量(只读常量)
const a = 1;
a = 3; //Uncaught TypeError: Assignment to constant variable.

(5)数据结构

//数据结构
let arr = [1,2,3];// let a = arr[0];
// let b = arr[1];
// let c = arr[2];let [a,b,c] = arr;console.log(a, b, c);

(6)对象结构

//对象结构
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}// const name = person.name;
// const age = person.age;
// const language = person.language;const{name:abc, age, language} = person;console.log(abc, age, language)

(7)字符串扩展

//字符串扩展
let str = "hello.vue";
console.log(str.startsWith("hello")); //true
console.log(str.endsWith(".vue")); //true
console.log(str.includes("e")); //true
console.log(str.includes("hello")); //true

(8)字符串模板

let ss = `<div><span>hello world<span>/div>`
console.log(ss);
//在字符串插入变量和表达式,变量名写在${}中,${}中科院放入JavaScript表达式
function func() {
return "这一个函数"
}
let name = "jack";
let age = 32;
let info = `我是${name}, 今年${age+10}了, 我想说: ${func()}`;
console.log(info);

(9)函数参数默认值

//在ES6之前,无法给一个函数参数设置默认值,只能采用变通的方法
function add(a, b) {
//判断是否为空,为空就给默认值
b = b || 1;
return a + b;
}
//传递一个参数
console.log(add(10));//现在可以这么写,直接给参数写上默认值,没给就使用默认值
function add2(a, b = 1) {
return a + b;
}
console.log(add2(10));//不定参数
function fun(...values) {
console.log(values.length);
}
fun(1,2) //2
fun(1, 2, 3, 4) //4

(10)箭头函数

//箭头函数
//以前声明一个方法
var print = function (obj) {
console.log(obj);
}var print2 = obj => console.log(obj);
print2("hello");var sum = function (a, b) {
c = a + b;
return a + c;
}
var sum2 = (a, b) => a + b;
console.log(sum2(11, 22));
var sum3 = (a, b) => {
c = a + b;
return a + c;
}
console.log(sum3(10, 20));const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}function hello(person) {
console.log("hello", + person.name);
}var hello2 = (param) => console.log("hello, " + param.name);
hello2(person); //hello,jackvar hello3 = ({name}) => console.log("hello, " + name);
hello3(person); //hello,jack

(11)新增的API

//1.新增的API
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}console.log(Object.keys(person)); // ["name", "age", "language"]
console.log(Object.values(person)); // ["jack", 21, Array(3)]
console.log(Object.entries(person)); //[Array(2), Array(2), Array(2)]
const target = {a: 1};
const source1 = {b: 2};
const source2 = {c: 3};
Object.assign(target, source1, source2);
console.log(target); //{a: 1, b: 2, c: 3}

(12)声明对象简写

//2.声明对象简写
const age = 23;
const name = "张三";
//传统
const person1 =  {age: age, name: name};
console.log(person1); //{age: 23, name: "张三"}//ES6:属性名和属性值变量名一样,可以省略
const person2 = {age, name};
console.log(person2); //{age: 23, name: "张三"}

(13)对象的函数属性简写

//3.对象的函数属性简写
let person3 = {
name: "jack",
//以前
eat: function (food) {
console.log(this.name + "在吃" + food);
},//箭头函数版,这里拿不到this
eat1: food => console.log(this.name + "在吃" + food),//箭头函数版,正确版
eat2: food => console.log(person3.name + "在吃" + food),//简写版
eat3(food) {
console.log(this.name + "在吃" + food);
}
}
person3.eat("apple"); //jack在吃appple
person3.eat1("apple");//在吃appple
person3.eat2("apple");//jack在吃appple
person3.eat3("apple");//jack在吃appple

(14)对象扩展运算符

//4.对象扩展运算符
//拷贝对象(深拷贝)
let person4 = {name : "Amy", age: 15}
let somone = {...person4}
console.log(somone) //{name: "Amy", age: 15}//合并对象
let age2 = {age2: 15}
let name2 = {name2: "Amy"}
let person5 = {name: "zhangsan"}
person5 = {...age2, ...name2}
console.log(person5) //{age2: 15, name2: "Amy"} //会覆盖之前的值

(15)map和reduce方法

//数组中新增了map和reduce方法
//map(): 接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回
let arr = ["1", "20", "-5", "3"];
// arr = arr.map((item) => {
// return item * 2;
// })arr = arr.map(item => item*2)
console.log(arr); //[2, 40, -10, 6]


//reduce()为数组中的每一个元素一次执行回调函数,不包括数组中被删除或从未被赋值的元素
//[2, 40, -10, 6]
//arr.reduce(callback, [initialValue])
/*
1.initialValue(上一次调用回调返回的值,或者是提供的初始值(initialValue))
2.currentValue(数组中当前被处理的元素)
3.index(当前元素在数组的索引)
4.array(调用reduce的数组)
*/
let result = arr.reduce((a,b) => {
console.log(“上一次处理后:”+a);
console.log(“当前正在处理:”+b);
return a + b;
},100)
console.log(result);
/*上一次处理后:100
map和reduce.html:33 当前正在处理:2
map和reduce.html:32 上一次处理后:102
map和reduce.html:33 当前正在处理:40
map和reduce.html:32 上一次处理后:142
map和reduce.html:33 当前正在处理:-10
map和reduce.html:32 上一次处理后:132
map和reduce.html:33 当前正在处理:6
map和reduce.html:36 138
*/

(16)promise异步操作
新建mock文件夹,在下面创建三个文件,内容如下:
user.json

{
"id": 1,
"name": "zhangsan",
"password": "123456"
}
user_corse_1.json{
"id": 10,
"name": "chinease"
}
corse_score_10.json{
"id": 100,
"score": 90
}
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>function get(url, data) {
return new Promise((resolve, reject) => {
$.ajax({
url: url,
data: data,
success: function (data) {
resolve(data);
},
error: function (err) {
reject(err)
}
})
});
}get("mock/user.json")
.then((data) => {
console.log("用户查询成功:", data)
return get(`mock/user_corse_${data.id}.json`);
})
.then((data) => {
console.log("课程查询成功:", data)
return get(`mock/corse_score_${data.id}.json`);
})
.then((data) => {
console.log("课程成绩查询成功:", data)
})
.catch((err) => {
console.log("出现异常", err)
});//结果:
//用户查询成功: {id: 1, name: "zhangsan", password: "123456"}
//课程查询成功: {id: 10, name: "chinease"}
//课程成绩查询成功: {id: 100, score: 90}

(17)模块化
新建js文件夹,创建三个文件内容如下:
hello.js

// export const util = {
// sum(a, b) {
// return a + b;
// }
// }export default {
sum(a, b) {
return a + b;
}
}//export {util}//export不仅可以导出对象,一切js变量都可以导出,比如:基本类型变量,函数,数组,对象。
user.jsvar name = "jack"
var age = 23
function add(a, b) {
return a + b;
}export {name, age, add}
main.jsimport util from "./hello.js"
import {name, add} from "./user.js"util.sum(1, 2);
console.log(name)
add(1, 3);

3、Vue

(1)声明式渲染,插值表达式等

//1.声明式渲染
let vm = new Vue({
el: "#app", //绑定元素
data: { //封装数据
name: "张三",
num: 1
},
methods: {  //封装方法
cancle() {
this.num--
}
}
});//2.双向绑定,模型变化,试图变化,反之亦然//3.事件处理//v-xx: 指令
//1.创建vue实例,关联页面的模板,将自己的数据(data)渲染到关联的模板,响应式的
//2.指令来简化对data的一些操作
//3.声明方法来做更复杂的操作,methods里面可以封装方法

(2)插值表达式
格式:{{表达式}}
说明:

该表达式支持JS语法,可以调用js内置函数(必须有返回值)
表达式必须有返回结果,例如1+1,没有结果的表达式不允许使用,如:let a = 1+1;
可以直接获取Vue实例丁的数据或函数
插值闪烁:使用{{}}在网速较慢时会出现问题,在数据为加载完成时,页面会显示出原始的‘{{}}’,加载完毕后才显示正确数据,我们称为插值闪烁。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
{{msg}} {{1+1}} {{hello()}} <br/>
<!-- <span v-html="msg"></span>
<br/>
<spn v-text="msg"></spn> --><!-- <a href="{{link}}">gogogo</a> -->
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
new Vue({
el: "#app",
data: {
msg: "<h1>Hello</h1>",
link: "http://www.baidu.com"
},
methods: {
hello() {
return "world"
}
}
})
</script>
</body>
</html>

(3)v-bind

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><!-- 给html标签的属性绑定 -->
<div id="app">
<a v-bind:href="link">gogogo</a><!-- class, style (class名:加上?) -->
<span v-bind:class="{active:isActive,'text-danger':hasError}"
v-bind:style="{color: color1,fontSize:size}">你好</span></div><script src="../node_modules/vue/dist/vue.js"></script><script>
let vm = new Vue({
el: "#app",
data: {
link: "http://www.baidu.com",
isActive:true,
hasError:true,
color1:'red',
size:'90px'
}
});
</script>
</body>
</html>

(4)v-model

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><!-- 表单项,自定义组件-->
<div id="app">
精通的语言:
<input type="checkbox" v-model="language" value="Java">java<br/>
<input type="checkbox" v-model="language" value="PHP">PHP<br/>
<input type="checkbox" v-model="language" value="Python">Python<br/>
选中了{{language.join(",")}}
</div>

<script>
let vm = new Vue({
el: "#app",
data: {
language: []
}
})
</script>
</body>
</html>

(5)v-on

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<!-- 事件中直接写js片段 -->
<button v-on:click="num++">点赞</button>
<!-- 事件指定一个回调函数,必须是Vue实例中定义的函数 -->
<button @click="cancle">取消</button>
<!-- -->
<h1>有{{num}}个赞</h1><!-- 事件修饰符 -->
<div style="border: 1px solid red;padding: 20px;" v-on:click.once="hello">
大div
<div style="border: 1px solid blue;padding: 20px;" @click.stop="hello">
小div <br/>
<a href="http://www.baidu.com" @click.prevent.stop="hello">去百度</a>>
</div>
</div><!-- 按键修饰符 -->
<input type="text" v-model="num" v-on:keyup.up="num+2" @keyup.down="num-1" @click.ctrl="num=10"><br/>提示:
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
new Vue({
el: "#app",
data: {
num: 1
},
methods: {
cancle() {
this.num--
},
hello() {
alert("点击了")
}
},
})
</script>
</body>
</html>

(6)v-for

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<ul>
<li v-for="(user,index) in users":key="user.name">
<!-- 1、显示user信息: v-for="item in items" -->
当前索引:{{index}} ==> {{user.name}} ==> {{user.gender}} ==> {{user.age}} <br/>
<!-- 2、获取数组下标:v-for="(item, index) in items" -->
<!-- 3、遍历对象:
v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key, index) in object"
-->
对象信息:
<span v-for="(v,k,i) in user">{{k}} == {{v}} == {{i}}; </span></span>
<!-- 4、遍历的时候都加上:key来区分不同数据,提供vue渲染效果 -->
</li>
</ul><ul>
<li v-for="(num, index) in nums" :key="index">{{num}}</li>
</ul>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
let app = new Vue({
el: "#app",
data: {
users: [{name: '柳岩', gender: '女', age: 21},
{name: '张三', gender: '男', age: 18},
{name: '范冰冰', gender: '女', age: 24},
{name: '刘亦菲', gender: '女', age: 18},
{name: '古扎丽娜', gender: '女', age: 25}],
nums:[1,2,3,4]
}
})
</script>
</body>
</html>

(7)v-if和v-show

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><!--
v-if:顾名思义,当前得到结果为true时,所在的元素才会被渲染
v-show:当得到结构为true时,所在的元素才会被显示
--><div id="app">
<button v-on:click="show = !show">点我呀</button>
<!-- 1、使用v-if显示 -->
<h1 v-if="show">if=看到我...</h1>
<!-- 2、使用v-show显示 -->
<h1 v-show="show">show=看到我</h1>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
new Vue({
el: "#app",
data: {
show: true
}
})
</script>
</body>
</html>

(8)v-else和v-else-if

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<button v-on:click="random=Math.random()">点我呀</button>
<span>{{random}}</span><h1 v-if="random>=0.75">
看到我啦?! &gt;=0.75
</h1><h1 v-else-if="random>=0.5">
看到我啦?! &gt;=0.5
</h1><h1 v-else-if="random>=0.2">
看到我啦?! &gt;=0.2
</h1><h1 v-else>
看到我啦?! &gt;0.2
</h1>

<script src="../node_modules/vue/dist/vue.js"></script><script>
let app = new Vue({
el: "#app",
data: { random: 1}
})
</script>
</body>
</html>

(9)计算属性和侦听器

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<!-- 某些结构是基于之前数据实时计算出来的,我们可以利用计算属性来完成 -->
<ul>
<li>西游记:价格:{{xyjPrice}},数量:<input type="number" v-model="xyjNum"> </li>
<li>水浒传:价格:{{shzPrice}},数量:<input type="number" v-model="shzNum"> </li>
<li>总价:{{totalPrice()}}</li>
{{msg}}
</ul>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
new Vue({
el: "#app",
data: {
xyjPrice: 99.98,
shzPrice: 98.80,
xyjNum: 1,
shzNum: 1,
msg: ""
},
methods: {
totalPrice() {
return this.xyjNum*this.xyjPrice+this.shzNum*this.shzPrice;
}
},
watch: {
xyjNum: function(newValue, oldValue) {
if(newValue >= 3) {
this.msg = "库存超出限制";
this.xyjNum = 3;
} else {
this.msg = "";
}
}
}
})
</script>
</body>
</html>

(10)过滤器

<!DOCTYPE html>
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head><body><!-- 过滤器常用来处理文本格式化的操作:过滤器可以用在两个地方:双花括号插值和v-bind表达式 -->
<div id="app">
<ul>
<li v-for="user in userList">
{{user.id}} ==> {{user.name}} ==> {{user.gender==1?"男":"女"}} ==>
{{user.gender | genderFilter}} ==> {{user.gender | gFilter}}
</li>
</ul>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>Vue.filter("gFilter", function (val) {
if (val == 1) {
return "男~~";
} else {
return "女~~";
}
})let vm = new Vue({
el: "#app",
data: {
userList: [
{ id: 1, name: "jacky", gender: 1 },
{ id: 2, name: "peter", gender: 0 }
]
},
filters: {
filters定义局部过滤器,只可以在当前vue实例中使用
genderFilter(val) {
if (val == 1) {
return "男";
} else {
return "女";
}
}
}
})
</script>
</body></html>

(11)组件化

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<button v-on:click="count++">我被点击了 {{count}} 次</button><counter></counter><button-counter></button-counter>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
//1.全局声明注册一个组件
Vue.component("counter", {
template: `<button v-on:click="count++">我被点击了 {{count}} 次</button>`,
data() {
return {
count: 1
}
}
});//2、局部声明一个组件
const buttonCounter = {
template: `<button v-on:click="count++">我被点击了 {{count}} 次</button>`,
data() {
return {
count: 1
}
}
};new Vue({
el: "#app",
data: {
count: 1
},
components: {
'button-counter':buttonCounter
}
})
</script>
</body>
</html>

(12)生命周期钩子函数

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body><div id="app">
<span id="num">{{num}}</span>
<button @click="num++">赞!</button>
<h2>{{name}}, 有{{num}}个人点赞</h2>
</div><script src="../node_modules/vue/dist/vue.js"></script><script>
let app = new Vue({
el: "#app",
data: {
name: "张三",
num: 100
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate() {
console.log("=============beforeCreate===============");
console.log("数据模型未加载:"+ this.name, this.num);
console.log("方法未加载:"+ this.show());
console.log("html模板未加载:" + document.getElementById("num"));
},
created: function() {
console.log("=============created===============");
console.log("数据模型已加载:"+this.name, this.num);
console.log("方法已加载:"+this.show());
console.log("html模板已加载:"+document.getElementById("num"));
console.log("html模板未渲染:"+document.getElementById("num").innerText);
},
beforeMount() {
console.log("=============beforeMount===============");
console.log("html模板未渲染:"+document.getElementById("num").innerText);
},
mounted() {
console.log("=============mounted===============");
console.log("html模板已渲染:"+document.getElementById("num").innerText);
},
beforeUpdate() {
console.log("=============beforeUpdate===============");
console.log("数据模型已更新:"+this.num);
console.log("html模板未更新:"+document.getElementById("num"));
},
updated() {
console.log("=============updated===============");
console.log("数据模型已更新:"+this.num);
console.log("html模板已更新:"+document.getElementById("num"));
}
})
</script>
</body>
</html>

4、vue模块化开发

vue官方文档:https://cn.vuejs.org/v2/guide/

(1)全局安装webpack,vue脚手架

npm install webpack -gnpm install -g @vue/cli-init

注意,安装之后,vue.cmd这个可执行文件在C:\Users\abc\AppData\Roaming\npm\node_modules@vue\cli-init\node_modules.bin,而不是C:\Users\abc\AppData\Roaming\npm目录,这有点奇怪,百度搜索了一下,也没找到合适的解决方法。不管了,切换到那个.bin目录下面执行vue.cmd是可以用的,OK,那就先这样用吧。或者把这路径加到path路径下面也可以全局使用vue命令了。

(2)创建vue项目vue-demo  
vue init webpack vue-demo

基本上选择默认的配置,一路回车就可以了,创建完成之后,发现vue-demo下面还有一个vue-demo文件夹,切换到这个目录,执行npm run dev就可以访问http://localhost:8080/#/ 这个demo页面了。

5、Element

官方文档:https://element.eleme.cn/#/zh-CN

vue模板

{"vue模板": {"prefix": "vue","body": ["<template>","<div></div>","</template>","","<script>","export default {","//import 引入的组件需要注入到对象中才能使用","components:{},","props:{},","data(){","//这里存数据","return{};","},","//计算属性","computed: {","","},","//监控data中数据变化","watch: {","","},","//方法","methods: {","","},","//声明周期 - 创建完成(可以访问当前this实例)","created() {","","},","//生命周期 - 挂载完成(可以访问DOM元素)","mounted() {","","},","beforeCreate() {},//生命周期 - 创建之前","beforeMount() {},//生命周期 - 挂载之前","beforeUpdate() {},//声明周期 - 更新之前","updated() {},//生命周期 - 更新之后","beforeDestroy() {},//生命周期 - 销毁之前","destroyed() {},//生命周期 - 销毁之后","activated() {},//缓存keep-alive","};","</script>","","<style>","</style>",],"description": "生成vue模板"}
}

console.log(“数据模型已更新:”+this.num);
console.log(“html模板未更新:”+document.getElementById(“num”));
},
updated() {
console.log(“=updated===”);
console.log(“数据模型已更新:”+this.num);
console.log(“html模板已更新:”+document.getElementById(“num”));
}
})

4、vue模块化开发

vue官方文档:https://cn.vuejs.org/v2/guide/

(1)全局安装webpack,vue脚手架

npm install webpack -gnpm install -g @vue/cli-init

注意,安装之后,vue.cmd这个可执行文件在C:\Users\abc\AppData\Roaming\npm\node_modules@vue\cli-init\node_modules.bin,而不是C:\Users\abc\AppData\Roaming\npm目录,这有点奇怪,百度搜索了一下,也没找到合适的解决方法。不管了,切换到那个.bin目录下面执行vue.cmd是可以用的,OK,那就先这样用吧。或者把这路径加到path路径下面也可以全局使用vue命令了。

(2)创建vue项目vue-demo  
vue init webpack vue-demo

基本上选择默认的配置,一路回车就可以了,创建完成之后,发现vue-demo下面还有一个vue-demo文件夹,切换到这个目录,执行npm run dev就可以访问http://localhost:8080/#/ 这个demo页面了。

5、Element

官方文档:https://element.eleme.cn/#/zh-CN

vue模板

{"vue模板": {"prefix": "vue","body": ["<template>","<div></div>","</template>","","<script>","export default {","//import 引入的组件需要注入到对象中才能使用","components:{},","props:{},","data(){","//这里存数据","return{};","},","//计算属性","computed: {","","},","//监控data中数据变化","watch: {","","},","//方法","methods: {","","},","//声明周期 - 创建完成(可以访问当前this实例)","created() {","","},","//生命周期 - 挂载完成(可以访问DOM元素)","mounted() {","","},","beforeCreate() {},//生命周期 - 创建之前","beforeMount() {},//生命周期 - 挂载之前","beforeUpdate() {},//声明周期 - 更新之前","updated() {},//生命周期 - 更新之后","beforeDestroy() {},//生命周期 - 销毁之前","destroyed() {},//生命周期 - 销毁之后","activated() {},//缓存keep-alive","};","</script>","","<style>","</style>",],"description": "生成vue模板"}
}

尚硅谷谷粒商城第一天 基础相关推荐

  1. M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档

    M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...

  2. 尚硅谷——谷粒商城项目开发记录——2021.11.22

    尚硅谷--谷粒商城项目开发记录--2021.11.22 概念: 1.对象优化: 新增的API: ES6 给 Object 拓展了许多新的方法,如: keys(obj): 获取对象的所有 key 形成的 ...

  3. 尚硅谷——谷粒商城项目开发记录——2021.11.19

    尚硅谷--谷粒商城项目开发记录--2021.11.19 出现错误 1.SpringBoot测试类出现Could not autowire. No beans of 'BrandService' typ ...

  4. 尚硅谷——谷粒商城项目开发记录——2021.11.21

    尚硅谷--谷粒商城项目开发记录--2021.11.21 概念: 1.var和let的区别: 作用域: var 声明的变量往往会越域 let 声明的变量有严格局部作用域 声明次数: var 可以声明多次 ...

  5. 尚硅谷——谷粒商城项目开发记录——2021.11.20

    尚硅谷--谷粒商城项目开发记录--2021.11.20 概念: 1.SpringCloud Alibaba: 简介: Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案.此 ...

  6. 尚硅谷谷粒商城第十二天 商品详情页及异步编排

    1. 商品详情 当用户搜索到商品,肯定会点击查看,就会进入商品详情页,接下来我们完成商品详情页的展示. 商品详情浏览量比较大,并发高,我们会独立开启一个微服务,用来展示商品详情. 1.1. 创建mod ...

  7. 尚硅谷谷粒商城第十六天 支付、秒杀

    1. 支付 订单搞定之后就是支付了,首先搭建支付工程. 1.1. 搭建环境 pom.xml <?xml version="1.0" encoding="UTF-8& ...

  8. 尚硅谷谷粒商城项目学习笔记-基础-P1项目搭建

    基础-P1项目搭建 0.虚拟机 1.项目架构 1.1Docker 1.1Docker命令 1.3Docker容器文件挂载与端口映射 1.2微服务-注册中心.配置中心.网关 1.3工具配置 1.3.1 ...

  9. 尚硅谷谷粒商城第九天 模板引擎-Thymeleaf

    1. 认识thymeleaf 1.1. 模板技术 把页面中的静态数据替换成从后台数据库中的数据.这种操作用jsp就可以实现.但是Spring boot 的架构不推荐使用Jsp,而且支持也不好,所以如果 ...

最新文章

  1. Git常见问题解决方案指北
  2. QTP自动化测试视频系列
  3. 边缘和智能,是谁在借谁上位?
  4. Hadoop处于风雨飘摇中
  5. android高度混淆,android – TextView与ImageSpan混淆行高
  6. cache buster issue application index and duplicate .library file
  7. 反射机制及其应用场景
  8. gitz之忽略warning:LF will be replaced by CRLF
  9. OpenCV3.4.3+Qt5.9.4(QtCreator)开发环境搭建
  10. linux中正则表达式的用法自解
  11. PHP_XLSXWriter 样式,使用PHP_XLSXWriter代替PHPExcel
  12. 【向生活低头】如何在Gold Wave软件中为声音添加背景音乐
  13. gin-binding参数效验
  14. Lick the habit 戒除恶习
  15. JAVA程序设计题——英雄对战游戏,定义一个描述战斗单位的英雄(Hero)类,此类必须包含以下成员变量:名称(name),生命值(life),技能1攻击力(damage1),防御力(defence)
  16. html班级管理,谈小学班级管理
  17. python结巴分词实例_python 结巴分词(jieba)详解
  18. iOS10全新方法实现推送+deviceToken无法获取或无效的解决
  19. 2565: 最长双回文串
  20. [Linux]termios

热门文章

  1. mac释放“其他”内存空间的解决方法
  2. UML基础(四)--顺序图
  3. 可信!Rancher容器解决方案通过可信云认证
  4. Oracle补丁快速下载的途径
  5. 领导问结婚情况什么意思_领导者如何在没有共识的情况下前进
  6. php表格生成器代码,PHP使用For循环生成table表格
  7. Handwiki:Wiki Encyclopedia of Knowledge
  8. Android事件传递可以这样理解
  9. 致----想要转行做Java的朋友们一封信
  10. 什么是缺页错误 Page Fault?